This is my warning.
warning: passing argument 2 of ‘memset’ makes integer from pointer without a cast
Then i changed as follows (make NULL to 0)
Before Change : memset(key, NULL, KEY_BYTES);
After Change : memset(key, 0, KEY_BYTES);
The warning is removed.
i am using linux & gcc compiler,C.
Is it correct action
Depending on implementation, the C standard library sometimes defines NULL as a zero integer (which would avoid the warning you saw) but sometimes defines NULL as zero cast into a void pointer. The latter implementation causes the warning you saw.
To answer your specific question, you should not be using NULL in this case. Regardless of the implementation, NULL is intended to be used as a null pointer, not a synonym for integer zero. If you want to use memset to fill a block of memory with zeroes, then pass zero as the second argument, not NULL.
Quoting from http://en.wikipedia.org/wiki/Stdlib.h:
NULL
The stdlib.h and stddef.h header files define
the macro NULL, which yields a null pointer
constant, and represents a pointer value that
is guaranteed not to point to a valid
address in memory.
Variants
NULL may be defined as a
constant expression equal to int zero,
long int zero, or zero cast to a void
* pointer:
#define NULL 0
#define NULL 0L
#define NULL ((void *) 0)
Although the null pointer constant is always
represented in C by the symbolic
constant 0 or by 0 cast to a void
pointer, the actual bit representation
of such a pointer is system-specific
and may contain one-bits.
Possibly NULL is defined as ((void*)0). Both versions work correctly, but the second looks better - memset requires a number and not a pointer.
The second parameter to memset is of type int. NULL is the null pointer constant in C. According to the standard:
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.
So, NULL may be defined as (void *)0 or equivalent. In such a case, your memset call is wrong because you are converting a pointer to an integer.
The other way is okay: if you use 0 where a null pointer is expected, the compiler will do the conversion for you. So, given a type T, the following sets both p and q to the null pointer:
T *p = NULL;
T *q = 0;
Further, given a pointer p, the following are equivalent:
if (p) ...
if (p != NULL) ...
if (p != 0) ...
This is because 0 is special: in pointer contexts, it is automatically converted to the null pointer constant. A pointer on the other hand, is never converted to an integer implicitly. Any integer other than 0 is also never converted to a pointer implicitly.
Finally, in the code below, even though i has the value 0, it is not a null pointer constant in the assignment to p:
int i = 0;
int *p = i;
The above will trigger a warning when compiled in conformant mode.
(The above is a bit of a digression, but I hope it is not completely off-topic.)
Yes, they have the same effect. The compiler must be treating NULL as a special NULL pointer (whereas some more primitive compilers simply #define NULL 0), and the second parameter of memset is of type int, so by changing it to 0 you are using the null value but satisfying the int requirement.
memset accepts second argument as a character not any pointer.In your first call,you pass the NULL which is a pointer points to nothing in C.That's why,it gave error.In the second call,you 're assigning 0 bytes to the memory given.
When using memset(key, NULL, KEY_BYTES);
NULL is the (void*)0 {ie; void* typecasted of int zero}.
and the memset 2nd argument should be of type "unsigned int"
That is why it is showing warning.
Depending upon the compiler you are using it will behave.
Using gcc will make to warned (regarding data typecast) and will just accept nearest possible available value out of the given argument value.
Related
So, I had an argument with my professor earlier defending that NULL is not a pointer, but he kept on insisting that it is because there is such a thing as NULL pointer. So, here I am now a little bit confused if NULL is really a pointer or not
I already tried search over the internet but couldn't find any answer, so my last resort is here
In C, NULL is a macro that expands to a null pointer constant.
7.19p3
The macros are
NULL which expands to an implementation-defined null pointer constant;
...
A null pointer constant is an integer constant expression with the value 0 (
e.g., 0, 1-1, 42*0LL, etc.) or such an expression cast to (void*).
6.3.2.3p3
An integer constant expression with the value 0, or such an expression
cast to type void *, is called a null pointer constant.66) If a null
pointer constant is converted to a pointer type, the resulting
pointer, called a null pointer, is guaranteed to compare unequal to a
pointer to any object or function.
Most common C implementations define NULL to be 0, 0L, or ((void*)0).
So you are correct. NULL need not be a pointer.
(IIRC, C++ doesn't even allow the (void*) cast in NULL, meaning NULL in C++ always has integer type. Because of that and because void* pointers
do not compare with regular pointers so readily in C++, C++>=11 now has a special nullptr keyword.)
NULL itself is not a pointer, it is a macro that can be used to initialize a pointer to the null pointer value of its type. When compared to a pointer, it compares equal if the pointer is a null pointer and unequal if the pointer is a valid pointer to an object of its type.
There is no semantic difference between char *p = 0; and char *p = NULL; but the latter is more explicit and using NULL instead of 0 is more informative in circumstances where the other operand is not obviously a pointer or if comparing to an integer looks like a type mismatch:
FILE *fp = fopen("myfile", "r");
if (fp == NULL) {
/* report the error */
}
Similarly, there is no semantical difference in C between '\0' and 0, they both are int constants. The first is the null byte, the second the null value. Using 0, '\0' and NULL wisely may seem futile but makes code more readable by other programmers and oneself too.
The confusion may come from misspelling or mishearing the null pointer as the NULL pointer. The C Standard was carefully proof read to only use null pointer and refer to NULL only as the macro NULL.
Note however that one the accepted definitions of NULL, #define NULL ((void*)0) makes NULL a null pointer to void.
There's nothing about the idea of a 'pointer to address 0' that's a problem.
The rule is that you're disallowed from derefencing it... it's allowed to exist, and if created will meet any criteria for "pointerhood" I can think of.
Just because it's not meaningfully a pointer to something...
Why is there a NULL in the C language? Is there a context in which just plain literal 0 would not work exactly the same?
Actually, you can use a literal 0 anyplace you would use NULL.
Section 6.3.2.3p3 of the C standard states:
An integer constant expression with the value 0, or such an
expression cast to type void *, is called a null pointer
constant. If a null pointer constant is converted to a pointer type,
the resulting pointer, called a null pointer, is guaranteed to
compare unequal to a pointer to any object or function.
And section 7.19p3 states:
The macros are:
NULL
which expands to an implementation-defined null pointer constant
So 0 qualifies as a null pointer constant, as does (void *)0 and NULL. The use of NULL is preferred however as it makes it more evident to the reader that a null pointer is being used and not the integer value 0.
NULL is used to make it clear it is a pointer type.
Ideally, the C implementation would define NULL as ((void *) 0) or something equivalent, and programmers would always use NULL when they want a null pointer constant.
If this is done, then, when a programmer has, for example, an int *x and accidentally writes *x = NULL;, then the compiler can recognize that a mistake has been made, because the left side of = has type int, and the right side has type void *, and this is not a proper combination for assignment.
In contrast, if the programmer accidentally writes *x = 0; instead of x = 0;, then the compiler cannot recognize this mistake, because the left side has type int, and the right side has type int, and that is a valid combination.
Thus, when NULL is defined well and is used, mistakes are detected earlier.
In particular answer to your question “Is there a context in which just plain literal 0 would not work exactly the same?”:
In correct code, NULL and 0 may be used interchangeably as null pointer constants.
0 will function as an integer (non-pointer) constant, but NULL might not, depending on how the C implementation defines it.
For the purpose of detecting errors, NULL and 0 do not work exactly the same; using NULL with a good definition serves to help detect some mistakes that using 0 does not.
The C standard allows 0 to be used for null pointer constants for historic reasons. However, this is not beneficial except for allowing previously written code to compile in compilers using current C standards. New code should avoid using 0 as a null pointer constant.
It is for humans not compilers.
if I see in the code p = NULL; instead of p = 0; it is much easier for me to understand that p is a pointer not the integer.
For compilers it does not matter, for humans does.
Same as we use definitions instead of "raw" values or expressions or human readable variable names like loopCounter instead of p755_x.
Why is there a NULL in the C language?
To help make clear the assignment implies a pointer and not an integer.
Example: strtok(char *s1, const char *s2); in both cases below receive a null pointer as the NULL and 0 are both converted to a char *. The first is usually considered better self-documentation. As a style issue, follow your group's coding standard.
strtok(s, NULL);
strtok(s, 0;
Is there a context in which just plain literal 0 would not work exactly the same?
Yes - when the original type is important.
0 is an int
NULL is a void *, or int, unsigned or long or long long, etc. It is implementation defined.
Consider a function that takes a variable number of pointers, with a sentinel null pointer to indicate the last.
foo("Hello", "World", NULL); // might work if `NULL` is a pointer.
foo("Hello", "World", 0);
As the arguments as 0 and NULL are not converted when passed to a ... function (aside from some promotions), the function foo() might not access them the same. Portable code would use:
foo("Hello", "World", (char*) NULL);
// or
foo("Hello", "World", (char*) 0);
A difference may also occur when NULL, 0 are passed to _Generic
The integer constant literal 0 has different meanings depending upon the context in which it's used. In all cases, it is still an integer constant with the value 0, it is just described in different ways.
Namely, the most common purposes of NULL pointer are:
To initialize a pointer variable when that pointer variable isn’t
assigned any valid memory address yet.
To check for a null pointer before accessing any pointer
variable. By doing so, we can perform error handling in pointer
related code e.g. dereference pointer variable only if it’s not
NULL.
To pass a null pointer to a function argument when we don’t want
to pass any valid memory address.(ref)
I have recently read Can I use NULL as substitution for the value of 0?
In short, in answers it was mentioned that using NULL as a substitution for the value of 0 is not suggested and will to lead to UB.
But in Is it safe to assume that the NULL constant is zero?, in short it was said that assuming if(!ptr)//ptr is a pointer is not completely wrong.
I know the question contents are different, but how could this be explained that using NULL as substitution for 0 is wrong , while if(!ptr) is true?
Because if(!ptr) is equivalent to if(ptr==0) (I assume this is right, not sure).
Also, I have used if(ptr==0) and it never worked wrong for me (to check if ptr is NULL), and I have assigned 0 to pointer ptr and when I debugged my code ptr was NULL. Are these two experiences safe?
From this NULL pointer reference:
To initialize a pointer to null or to assign the null value to an existing pointer, a null pointer constant (NULL, or any other integer constant with the value zero) may be used.
[Emphasis mine]
So the integer constant 0 is a valid null pointer constant.
But note that it doesn't mean that the actual null value on the hardware platform used is equal to 0, it only means that the compiler accepts 0 as an alias for the system-dependent null pointer constant.
Also, a null pointer is always "false" and a non-null pointer is always "true", which is why a condition like if (ptr) or if (!ptr) works well.
I know the question contents are different, but how could this be
explained that using NULL as substitution for 0 is wrong , while
if(!ptr) is true? Because if(!ptr) is equivalent to if(ptr==0) (I
assume this is right, not sure).
if(!ptr) is equivalent to if (!ptr != 0) by the semantics of if statements, which is equivalent to if (ptr == 0) by the semantics of the !, !=, and == operators with pointer operands. This is nicely consistent, but it does not follow from anything you know about operations on integers. Operations on pointers have their own set of rules.
And that is exactly the take home. Because an integer constant with value zero -- which is a source code construct -- is, among other things, a null pointer constant, it by definition compares equal to all null pointer values. This says nothing at all about the representation of null pointer values of any type, about the type of the expression to which the NULL macro expands, or about the value produced by converting to integer any particular null pointer value that is not represented in source code as an integer constant with value zero.
NULL is a macro. It is an "implementation-defined null pointer constant;" C17dr § 7.19 3.
An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. C17dr § 6.3.2.3 3
So NULL may have the type of void *, int, long, unsigned, long long, etc.
0 is an int constant.
When its OK.
Assignment: Both below assign p,q to some null pointer.
void *p = 0;
void *q = NULL;
Code compare: p==q is true as all null pointers equate. All null pointers do not equate to the address of any object. !p and !q are both 1.
When its not OK.
Function argument
The type and its size of NULL is implementation defined.
printf("%d\n", 0); // OK - %d expects an int
printf("%d\n", NULL); // Not OK, NULL could be long, void *, etc.
printf("%p\n", NULL); // Not OK, NULL could be int, long, long long
printf("%p\n", (void*) NULL); // OK - %p expects a void*
_Generic()
The result of the below is implementation defined.
_Generic((NULL), \
void *: "void *", \
int: "int", \
long: "long", \
default: "TBD")
Macro compare
The below resulted in "error: operator '*' has no right operand" for me. #if !0 was fine.
#if !NULL
#error foo
#endif
This question already has answers here:
Is ((void *) -1) a valid address?
(3 answers)
Closed 5 years ago.
The function returns -1.
However, what is the meaning of (void*) in the following code:
can it work without it ?
test = shmat(shm_id, NULL, 0);
if (test == (void *)-1) {
/* handle shmat failure */
}
shmat has the following prototype:
void *shmat(int shmid, const void *shmaddr, int shmflg);
i.e. it returns a pointer to void, not an integer.
On error it will return the integer -1 cast to a pointer to void. From Linux manpages shmat(2):
On success, shmat() returns the address of the attached shared memory segment; on error, (void *) -1 is returned, and errno is set to indicate the cause of the error.
That is how you must do the comparison properly to check for an error return. The C11 standard says the following about the operator == in 6.5.9p5-6:
5 Otherwise, at least one operand is a pointer. If one operand is a pointer and the other is a null pointer constant, the null pointer constant is converted to the type of the pointer.
If one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of void, the former is converted to the type of the latter.
6 Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.109)
That is, the standard defines behaviour for exactly 2 conversions: either one operand is a pointer to void, and the other operand is a pointer to something else; or one operand is a pointer, and the other operand is the null-pointer constant (i.e. 0, or (void*)0, or so). Since -1 without casts is neither a null-pointer constant, nor a pointer, the standard doesn't specify any behaviour for such case, thus the behaviour is undefined "by the omission of any explicit definition".
test == -1 is wrong, and test == (void *) -1 is right(ish).
As it turns out this is still a grey area. -1 is an int and on my computer, it is 32 bits. The conversion of an integer to pointer is defined by the implementation. The GCC manuals say:
A cast from pointer to integer discards most-significant bits if the pointer representation is larger than the integer type, sign-extends[2] if the pointer representation is smaller than the integer type, otherwise the bits are unchanged.
With footnote 2 saying
Future versions of GCC may zero-extend, or use a target-defined ptr_extend pattern. Do not rely on sign extension.
Thus it would mean that (void *)-1 might become incorrect too; the safer way would be to write it as (void *)(intptr_t)-1.
For some reason the (void *)0, i.e. the null pointer, is not used to signal an error condition (even though use of such a pointer in C would be erroneous standard-wise).
It is type casting.
The function shmat() returns a void*, so type casting is used to convert -1 (int) to the correct type (void*).
Actually, yes it could work but you'll get some warnings from the compiler.
Never ignore warnings they can hide bugs.
NULL appears to be zero in my GCC test programs, but wikipedia says that NULL is only required to point to unaddressable memory.
Do any compilers make NULL non-zero? I'm curious whether if (ptr == NULL) is better practice than if (!ptr).
NULL is guaranteed to be zero, perhaps casted to (void *)1.
C99, §6.3.2.3, ¶3
An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.(55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
And note 55 says:
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant.
Notice that, because of how the rules for null pointers are formulated, the value you use to assign/compare null pointers is guaranteed to be zero, but the bit pattern actually stored inside the pointer can be any other thing (but AFAIK only few very esoteric platforms exploited this fact, and this should not be a problem anyway since to "see" the underlying bit pattern you should go into UB-land anyway).
So, as far as the standard is concerned, the two forms are equivalent (!ptr is equivalent to ptr==0 due to §6.5.3.3 ¶5, and ptr==0 is equivalent to ptr==NULL); if(!ptr) is also quite idiomatic.
That being said, I usually write explicitly if(ptr==NULL) instead of if(!ptr) to make it extra clear that I'm checking a pointer for nullity instead of some boolean value.
Notice that in C++ the void * cast cannot be present due to the stricter implicit casting rules that would make the usage of such NULL cumbersome (you would have to explicitly convert it to the compared pointer's type every time).
From the language standard:
6.3.2.3 Pointers
...
3 An integer constant expression with the value 0, or such an expression cast to type
void *, is called a null pointer constant.55) If a null pointer constant is converted to a
pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
...
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.
Given that language, the macro NULL should evaluate to a zero-valued expression (either an undecorated literal 0, an expression like (void *) 0, or another macro or expression that ultimately evaluates to 0). The expressions ptr == NULL and !ptr should be equivalent. The second form tends to be more idiomatic C code.
Note that the null pointer value doesn't have to be 0. The underlying implementation may use any value it wants to represent a null pointer. As far as your source code is concerned, however, a zero-valued pointer expression represents a null pointer.
In practice is the same, but NULL is different to zero. Since zero means there's a value and NULL means there isn't any. So, theoretically they are different, NULL having a different meaning and in some cases that difference should be of some use.
in practice no, !ptr is correct