This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Does the evil cast get trumped by the evil compiler?
Hello,
If I can modify a constant through a pointer, then what is the purpose of it?
Below is code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int a = 10;
int *p = (int *)&a;
printf("Before: %d \n", a);
*p = 2;
/*a = 2; gives error*/
printf("After: %d \n", *p);
return 0;
}
OUTPUT:
Before: 10
After: 2
Press any key to continue . . .
Using Visual Studio 2008.
The reason you could modify the value is because you did a pointer typecast that stripped off the constness:
int *p = (int *)&a;
This typecasts a const int* (namely &a) to an int *, allowing you to freely modify the variable. Normally the compiler would warn you about this, but the explicit typecast suppressed the warning.
The main rationale behind const at all is to prevent you from accidentally modifying something that you promised not to. It's not sacrosanct, as you've seen, and you can cast away constness with impunity, much in the same way that you can do other unsafe things like converting pointers to integers or vice-versa. The idea is that you should try your best not to mess with const, and the compiler will warn you if you do. Of course, adding in a cast tells the compiler "I know what I'm doing," and so in your case the above doesn't generate any sort of warnings.
If i can modify a constant through a
pointer then what is the purpose of
it? below is code:
This is Undefined Behavior and should be avoided at all costs:
§ C99 6.7.3p5
If an attempt is made to modify an
object defined with a const-qualified
type through use of an lvalue with
non-const-qualified type, the
behavior is undefined.
Related
I have a non-copyable C++ lambda which captures a unique_ptr, and certain situations when compiling with Apple Clang as Objective-C++ cause the lambda to get converted to a block pointer, at which point the compilation fails due to an attempted copy of the lambda. A simple example is as follows:
int main(int argc, const char * argv[])
{
std::unique_ptr<int> myHeapInt = std::make_unique<int>(4);
int myStackInt = 0;
auto myLambda = [&, myHeapInt = std::move(myHeapInt)]()
{
myStackInt = *myHeapInt;
};
if(bool(myLambda)) //Error ar this point
{
*myHeapInt = 5;
}
std::invoke(myLambda);
return 0;
}
The error is as follows:
Call to implicitly-deleted copy constructor of 'const lambda...
Implicit capture of lambda object due to conversion to block pointer here
Is there a way around this conversion?
What is that bool(myLambda)? I have no clue.
The only thing you can do with a lambda is evoke it: myLambda(). You cannot test for whether it exists or anything.
So, I'm not entirely seeing the relevance of Objective-C++ here, as this code doesn't compile as C++ either:
objc++-noncopy-lambda.cpp:15:9: error: cannot convert '(lambda at objc++-noncopy-lambda.cpp:9:21)' to 'bool' without a conversion operator
if (bool(myLambda))
^~~~~~~~~~~~~
1 error generated.
The error message is different; I assume there's some attempt at implicitly converting lambdas to blocks in Objective-C++, I've tried to stay away from weird edge cases like that, but it seems that in the absence of an operator bool it might try the conversion to a block first.
Either way the code you're attempting to write doesn't make any sense and the compiler is correctly rejecting it.
I see in the comments that you're actually trying to do something different. Could you perhaps post a reduced version of the code you're actually trying to write, which supposedly compiles as C++ but not as Objective-C++?
I was trying to compile a templated header-file class replacement for std::function (github.com/Naios/function2) as Objective-C++, which implements a vtable and optimises it if the callable implements operator bool() or can be converted to bool.
In the end I just decided to disable this optimisation if compiled as Objective-C++ as converting to a block pointer is by design in Clang for block-lambda interoperability (http://clang.llvm.org/docs/LanguageExtensions.html#interoperability-with-c-11-lambdas).
On iOS 11, when I intentionally create objects which would turn out to be tagged pointers, they start with 0xB, instead of the 0x0000000000000026, 0x000000000000001c, 0x000000000000005a values that are showing up in my crash reports as invalid addresses. I think these are likely tagged pointers, but they aren't formatted like tagged pointers that I see in the debugger.
What about 0x0000000000000010, 0x0000000000000020, 0x0000000000000030 ? They all have a trailing 0, but they sure look suspiciously small to be real pointers.
The implementation details of tagged pointers changes from release to release and architecture to architecture. With that said, those really don't look like tagged pointers.
What is most likely is that some piece of code is dereferencing into a struct or object that is unexpectedly NULL or nil.
Run this code:
struct bob {
void *a;
void *b;
void *c;
char d[42];
};
int main(int argc, const char * argv[]) {
struct bob *fred = NULL;
fred->d[2] = 'q';
return 0;
}
You'll get this crash (on x86_64): Thread 1: EXC_BAD_ACCESS (code=1, address=0x1a)
That is, it is trying to dereference through 0x0. So, more likely than not, you have a struct/object reference that is NULL and your code is trying to dereference an element or instance variable that is offset by the hex #s you listed from the beginning.
Hi this is third day of mine using Objective-C today I was writing few simple programs and i ecncountered the following warning
main.m:19:5: warning: passing argument 1 of 'NSLog' makes pointer from integer without a cast [enabled by default]
NSLog(res);
which finally resulted in the Segmentation fault.. Here is my program..
#import <Foundation/Foundation.h>
#interface SomeClass: NSObject
{
int x;
}
#property int x;
#end
#implementation SomeClass
#synthesize x;
#end
int main(){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
SomeClass * obj = [[SomeClass alloc]init];
obj.x =20;
int res = obj.x;
NSLog(res); //error
/* But the error was not seen when I replaced the above statement with
NSLog(#"The value is : %d",res);
*/
[pool drain];
return 0;
}
The error message that I got was :
Compiling the source code....
$gcc `gnustep-config --objc-flags` -L/usr/GNUstep/System/Library/Libraries -lgnustep-base main.m -o demo -lm -pthread -lgmpxx -lreadline 2>&1
main.m: In function 'main':
main.m:19:5: warning: passing argument 1 of 'NSLog' makes pointer from integer without a cast [enabled by default]
NSLog(res);
^
In file included from /usr/GNUstep/System/Library/Headers/Foundation/NSObject.h:30:0,
from /usr/GNUstep/System/Library/Headers/Foundation/FoundationErrors.h:29,
from /usr/GNUstep/System/Library/Headers/Foundation/Foundation.h:33,
from main.m:1:
/usr/GNUstep/System/Library/Headers/Foundation/NSObjCRuntime.h:146:16: note: expected 'struct NSString *' but argument is of type 'int'
GS_EXPORT void NSLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
^
Executing the program....
$demo
Segmentation fault (core dumped)
Please help by making me understand why NSLog behaves like this ? Where did I go wrong?
Thank you...
You can't use the NSLog like this, You need to specify the control string and use like:
NSLog(#"%d",res);
The format should be specified for NSLog(), please check the NSLog and NSLogv reference for more information
NSLog
Logs an error message to the Apple System Log facility.
void NSLog ( NSString *format, ... );
Discussion
Simply calls NSLogv, passing it a variable number of arguments.
Availability
NSLogv
Logs an error message to the Apple System Log facility.
void NSLogv ( NSString *format, va_list args );
Discussion
Logs an error message to the Apple System Log facility (see man 3
asl). If the STDERR_FILENO file descriptor has been redirected away
from the default or is going to a tty, it will also be written there.
If you want to direct output elsewhere, you need to use a custom
logging facility.
The message consists of a timestamp and the process ID prefixed to the
string you pass in. You compose this string with a format string,
format, and one or more arguments to be inserted into the string. The
format specification allowed by these functions is that which is
understood by NSString’s formatting capabilities (which is not
necessarily the set of format escapes and flags understood by printf).
The supported format specifiers are described in “String Format
Specifiers”. A final hard return is added to the error message if one
is not present in the format.
In general, you should use the NSLog function instead of calling this
function directly. If you do use this function directly, you must have
prepared the variable argument list in the args argument by calling
the standard C macro va_start. Upon completion, you must similarly
call the standard C macro va_end for this list.
Output from NSLogv is serialized, in that only one thread in a process
can be doing the writing/logging described above at a time. All
attempts at writing/logging a message complete before the next thread
can begin its attempts.
The effects of NSLogv are not serialized with subsystems other than
those discussed above (such as the standard I/O package) and do not
produce side effects on those subsystems (such as causing buffered
output to be flushed, which may be undesirable). Availability
You cant declare the NSLog like that see the tutorial for NSLog its may be useful for you.
Objective-C has a number of built-in data types:
int – integer constant
float – real numbers with fractional component
double – double precision floating point number
char – a single character
short – short integer (2 bytes)
long – double short
long long – double long
BOOL – boolean
The utility function NSLog() can be used to print to the debug console in Xcode. NSLog() uses the NSString formatting services. The easiest way to create a NSString is to use the #”" notation. Inside a format string a % is a placeholder for a value. The character after the % determines the value expected, be it an int or a float and so on. If we declare an integer “int i = 5″ and want to print the value of i with NSLog() we can do it with NSLog(#”The value of i is %d”, i);
You can use %d to print the value of an int, %f for a float and double, %c for a char. For a full listing of all format specifiers supported by NSString formatting methods read through the documentation.
For More Reference Click Here
keep learning..:)
The 1st argument to NSLog is an NSString that should be a string with 0 or more format specifiers.
Use:
NSLog(#"res = %d", res);
or just:
NSLog(#"%d", res);
Have a look at the reference docs for NSLog for details.
You should specify the compiler that what kind of data type you want to print in Log,
NSLog(#"%d",res);
You should not never use NSLog(variable) directly. Instead, use NSLog(#"%d", variable) for integers or NSLog(#"%#", object) for objects.
I have a method , which takes the following argument.
void callAMethood(const void *iVar){}
now here i am not clear on how should i pointer
the following seems to be quite simple,where i just pass the address instead of value.
NSString *a=#"Hi";
callAMethood(&a);
But, the following seems to work well, but understanding the syntax is difficult.
char const * const a="HI";
callAMethood(&a);
or even this works callAMethood(a);
As xlc points out, both are wrong.
NSString *a=#"Hi";
callAMethood(&a); // This passes a NSString **
char const * const a="HI";
callAMethood(&a); // This passes a char const * const *
Both work, because a pointer to a pointer can stil be cast to a void *.
It is incredibly unlikely that you intended either, though.
Take advantage of C being type-checked at compile time and be more specific with your types.
void awesome_function(NSString *amazingString);
NSString *yay = #"oh my god yes";
awesome_function(yay); // ok
awesome_function(&yay); // compiler error
In short: unless you have a very good reason for using a void * (which I would consider unlikely for a Cocoa(Touch) app), don't.
If you don't want compile-time type checking, use something like Python. If you want to be able to handle different Objective C object types, that's what id is for.
You ask what you should pass to the function (it is not the declaration of a method):
void callAMethood(const void *iVar) {...}
The answer is nobody can tell you!
Your function takes a value of type void * - this type is typically used in C to mean a "pointer to anything". It is not a type that would be used for a function that took a pointer to any object, that would be id.
But that doesn't get us very far, as we've no idea what callAMethood is expecting we've no idea what to pass it - we cannot tell you the answer.
Now you give the example:
NSString *a = #"Hi";
callAMethood(&a);
That is a valid call, it passes a pointer to the variable a. However:
callAMethood(a);
is also a valid call, it passes the pointer which is stored in the variable a. Without any knowledge of what callAMethood is expecting we cannot tell you which is the correct call. The same applies to your second example.
HTH
Every pointer can be converted to void * implicitly.
EDIT:
As Kevin said, only data pointer.
As CRD said,
The answer is nobody can tell you!
without the information of the function of callAMethood. All of those invoking are valid grammatically(can be compiled), howerver, invalid semantically usually unless callAMethood really doesn't care about which type iVar(e.g. it just prints the pointer).
What people said above is correct but you can also use UTF8String to get a const char * from a NSString
const char * myStr = [a UTF8string];
callMehtod(myStr);
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
I have the following structure that is defined in a header file for a library that a vendor has given to us.
typedef struct {
int iLen;
int iType;
int state;
unsigned char data[1200];
} TCardCmdRespond;
I have created a structure in C# that I think matches it.
[StructLayout(LayoutKind.Sequential)]
public struct TCardCmdRespond
{
public int iLen;
public int iType;
public int state;
public byte[] data;
}
I have a few things to point out here. I am not sure what an unsigned char array should map to. I initially guessed that unsigned char should map to char but char in C# is Unicode so that doesn't seem like it would work. I also tried mapping it to a byte. I also don't know if the length 1200 will be significant to the marshaler and if so, how to designate it.
I have the following method in my monotouch app that takes the structure as a parameter.
[Export("OnRecvData:")]
public void OnRecvData(TCardCmdRespond respond)
{
...
}
The method is invoked by the library via a selector. The method is invoked without a problem. The problem arises when I look at the data contained in the structure. The numbers are extremely high when I am expecting them to be in the range between 1-3 (comparable objective-c code shows the iType to be in this range). I have tried using bit-converter to reverse the byte order in case it is an endianness problem that the marshaler didn't solve for me. The numbers are still high so I think the problem goes beyond simple endianness.
Further problems arise when I try to pull the data out of the char array. It isn't null but trying to access it in any way beyond a null check crashes the application with an EXC_BAD_ACCESS (SIGABRT)
My workaround solution is to write a wrapper for this in objective-c that breaks the structure apart into parameters instead. Then create a library that wraps it up and bind that instead. My objective-c skills are not so hot and that is a slow process however.
Is there a way that I can make this work without having to wrap this up in an objective-c library?
Your C# definition is incorrect.
The C version includes an inline block of 1200 bytes for the array, while your C# version contains a pointer to an array (4 bytes).
You can look at this:
http://msdn.microsoft.com/en-us/library/z6cfh6e6.aspx