This question already has answers here:
warning: assignment makes integer from pointer without a cast
(5 answers)
Closed 6 years ago.
the code bellow works as it needs to work.
void TstPointer(int *Pointer)
{
*Pointer = 3;
}
int main()
{
int number = 1;
int *ptr = &number;
TstPointer(ptr);
printf("%d\n", number);
}
But when i switch types to char it doesnt work.
void TstPointer(char *Pointer)
{
*Pointer = "Hell1";
}
int main()
{
char *Hello = "Hello";
TstPointer(Hello);
printf("%s\n", Hello);
}
warning: assignment makes integer from pointer without a cast [-Wint-conversion]
*Pointer = "Hell1";
Pass the reference of Hello to your method (&Hello) as you do with int -
int *ptr = &number;
TstPointer(ptr);
While doing *Pointer = "Hell1"; your compiler warned you. You chose to ignore that which possibly invokes the undefined behavior.
In general , to copy to a pointer, use strcpy() but in that case, that will cause problem, as Pointer points to a string literal which you're not allowed to change.
You need to make sure that the memory is writable before trying to write into that memory location. Either use memory allocator function, or create an array and make the pointer point to the start of the array.
In your TstPointer method, when you do *Pointer = "Hell1";, you are generating the warning.
This is because, if Pointer is a char pointer, then *Pointer is a char variable. And you are assigning a string constant to a char variable which is wrong.
To solve this issue, I think you ought to use a double pointer in the function parameter as pass the address (of the pointer) in the main!
EDIT:
You are getting the warning because when you assign a string constant to a variable (char pointer or array, usually), that variable stores the address of the beginning of the string constant. Now, when the lvalue is not char pointer type, but is just a char variable, some implicit conversion takes place to assign (fit) the "address" into a normal char variable, which in turn gives the warning. But, we know char cannot accommodate a memory address, and thus will usually result in a segfault when printed!
Related
I get a warning when i point to a pointer. I am not sure why; the types are the same.
char delay_buffer1[40];
char delay_buffer2[40];
char** delay_buffer_front;
delay_buffer_front = &delay_buffer1;
the objective is to swap buffers:
void swap_string_buffer(void** pointer, void* buffer1, void* buffer2) {
printf("pointer: %u. buffer1: %u. buffer2 %u\n", pointer, buffer1, buffer2);
if(*pointer == buffer1) *pointer = buffer2;
else *pointer = buffer1;
}
example code:
copy_content_to(delay_buffer_front);
swap_string_buffer((void**) delay_buffer_front, (void*) delay_buffer1,(void*)delay_buffer2);
fprintf(file, "%s", delay_buffer_front);
warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
delay_buffer_front = &delay_buffer1;
the types are the same.
No, they aren't. You're probably confused (this is quite common) by the fact, that the identifier of an array evaluates to a pointer to its first element in nearly all contexts (exceptions are e.g. with the operators & and sizeof).
But that doesn't change the fact that an array is an array and a pointer is a pointer.
This is a pointer to a pointer:
char **delay_buffer_front;
What you probably wanted was a pointer to an array:
char (*delay_buffer_front)[40];
Or you might simply have wanted a plain pointer pointing to the first element of the array:
char *delay_buffer_front;
With that declaration, you can just assign the array's identifier because as explained above, it evaluates to such a pointer:
char *delay_buffer_front = delay_buffer1;
It means exactly that, the two pointers are incompatible. It's more an error than a warning.
You probably want this:
char* delay_buffer_front;
delay_buffer_front = delay_buffer1;
instead of:
char** delay_buffer_front;
delay_buffer_front = &delay_buffer1;
As all you want is to swap the buffers you dont have to create a pointer to a pointer. Simply create an intermediate pointer of similar type and use it for swapping.
char* delay_buffer_front; //Intermediate pointer to store the address of first buffer
delay_buffer_front = delay_buffer1; //Store the address of the first buffer in the
//intermediate pointer.
We are dealing with a constant pointer,
so the address it holds cannot change.
But the content of that referenced memory address is supposed to be mutable...
Still,I get compilation/segmentation fault errors when trying to do so.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char * const c_ptr = "firstValue"; // now c_ptr is a const ptr to an immutable string literal,
//we can't change it unless we declare char [] instead
printf("%s",c_ptr);
*c_ptr="hsdsdsd"; // better to use strcpy(c_ptr, "hsdsdsd");
printf("%s",c_ptr);
return 0;
}
main.c: In function 'main':
main.c:8:8: warning: assignment makes integer from pointer without a cast [enabled by default]
*c_ptr="hsdsdsd";
Segmentation fault (core dumped)
Well, the data that the pointer points at can change for a constant pointer, but not when you initialize it using a string literal. They have the rather curious property of having type char *, but being unable to change.
So, you can do:
char data[10] = "foobar";
char * const ptr = data;
printf("%s\n", ptr); // prints foobar
*ptr = 'z';
printf("%s\n", ptr); // prints zoobar
char * const c_ptr means a non-const pointer to const data. Meaning that you made the pointer variable itself read-only, but not the pointed-at data.
If you do *c_ptr = 'a' then the compiler wouldn't prevent it, because you told it that the pointed-at data is read/write. Which isn't true in this case, it is a string literal and writing to it will cause undefined behavior, which is why you get a crash.
C11 6.4.5/7
If the program attempts to modify such an array, the behavior is
undefined.
Fix the code by changing the declaration to const char* c_ptr.
Or alternatively const char* const c_ptr.
Now as it turns out, this is immutable, because if you would now attempt strcpy(c_ptr, "str") you would get an invalid pointer conversion, since the function expects a char*.
*c_ptr="hsdsdsd"; is nonsense and will not compile on a compliant C compiler, because you try to assign an address to a single char variable, which is not allowed. (A constraint violation of the simple assignment rules).
First, C strings are null terminated char arrays, and you cannot assign arrays, you have to change each element of it.
Also, generally the compiler put string literals like "firstValue" into a readonly memory section, so you cannot change it, you will have to use a char array to initialize the string.
char s[] = "firstValue";
const char*const ptr = s;
ptr[0] = 'z'; // change contents pointed by ptr, or:
strncpy(ptr, "abc", 3);
malloc() function is said to return a null pointer or a pointer to the allocated space. Suppose for a string we make the statement:
char* ptr = malloc(size)
Isn't ptr a pointer that would point to a pointer?
Isn't :
char** ptr = malloc(size)
supposed to be the correct way to declare the pointer to char?
The compiler however doesn't give a warning when we do either, the warning it does give is for the format specifier if used.
How should we declare this and why? Also, how would char** be used?
No, 'ptr' would contain the pointer returned by 'malloc'. You are assigning the returned pointer, not taking its address.
The char * denotes a char pointer. Malloc will return a void * pointer (that will be automatically converted to whatever pointer you're trying to assign).
The char ** denotes a char * pointer. This is a pointer to a pointer.
If you think of a pointer as a map you have that char * is a map to a char, void * is a map to something mysterious and char ** is a map to another map that leads to a char. So
char* ptr = malloc(size);
Is the correct one, because you want a map to something, not a map to a map.
*ptr is a pointer to a char, which is often used to manage an array
or a string.
**ptr is a pointer to a pointer to a char, which is often used to
manage a matrix (array of arrays) or a string array.
char *charPtr = malloc(50);
char *charPtr; *charPtr = malloc(50);
I have been creating pointers in C like the examples above. Is it okay to say that these two are the same in C?
Is it okay to say that these two are the same in C?
No, you need to either initialize the pointer.
char *charPtr = malloc(50); // initialization
Or, you declare it first, then assign it later:
char *charPtr; // declaration
charPtr = malloc(50); // <-- assignment - do NOT add * here as the you already declared `charPtr` as a pointer
Note that doing it like you did (2nd case) was wrong:
char *charPtr;
*charPtr = malloc(50); // <-- WRONG, the * here is deference operator
No, they are not the same. In this case
char *charPtr;
*charPtr = malloc(50);
You are
Dereferencing an uninitialized pointer and that would cause Undefined Behavior.
Assigning a pointer to an integer of different size without casting. Although conversion from pointer to integer and the other way is defined according to the c standard, there are some things you should consider. If this code has been working for you it's because of Undefined Behavior mentioned above. You never know that it's happening until something bad happens which might happen all the time or never, or sometimes, you really never know.
The * plays two different roles here, in the first case
char *charPtr;
it simply indicates that charPtr is a pointer, whereas in
*charPtr = malloc(50);
it's the dereference operator.
Of course, the * is also the multiplication operator but it's interpretation by the compiler depends on the context where it appears.
No. The first declares charPtr as a pointer to char, and it contains the return value of malloc.
The second declares charPtr as a pointer to char. It then says that the value charPtr points to should be set to the return value of malloc. This is wrong. The pointer is uninitialized, and to say what it should point at is undefined behavior. In addition, assigning a void * to a char should generate a compiler diagnostic.
This has no runtime error
int main()
{
char *p = "Hello";
}
This gives runtime error
int main()
{
int *p;
*p = 5;
}
I cant understand the reason why this is happening. Would appreciate any kind of help.
Your first example points pointer p to a literal string, so p is pointing to valid memory.
Your section declares the pointer p but does not point to to any memory address. Then the next statement *p = 5 dereferences p, which tries to store 5 at the memory address stored in pointer p. Since you have not pointed p to valid memory, your application crashes.
Your second snippet is undefined behaviour as the pointer is uninitialised.
Your first snippet could get you into trouble too: you ought to write const char *p = "Hello";. This is because the string text will be added to a table of string literals by the C runtime library. It's undefined behaviour to modify it. Using const helps enforce that.
The first program sets the value of the pointer, and is well-defined (so long as you don't attempt to modify the string).
The second program assigns a value through an uninitialized pointer (and therefore has undefined behaviour).
The following is a rough equivalent of the first program, but using int:
int main()
{
int val = 5;
int *p = &val;
}