Lets say I have a variable:
char** code;
I then do:
*code[0] = "Lucas"
Is it valid to say that, **code holds an array of pointers (*code is the array which I am making strings) and that *code[0] will equal "Lucas" and that *code[0][2] will equal 'c'?
Sorry if it seems elementary, I am getting very confused with double pointers! Thanks in advance!
-Lucas Giancola
Is it valid to say that, **code holds an array of pointers
No it is not. You have allocated space for a single pointer. You have told the compiler that that pointer will point at another pointer (that you have not created yet) that points to a character (that you have not created yet either)
*code[0] = "Lucas"
Is not valid code and doesnt compile
prog.cpp:6:8: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
*f[0] = "Lucas";
If you just have
char** code;
*code[0] = "Lucas";
you'll run into undefined behavior since you did not allocate any memory for code.
You'll need to use:
char** code = malloc(SOME_SIZE*sizeof(*code));
Even after that, using:
*code[0] = "Lucas";
is not good. There are couple of problems with that.
code[0] is a pointer. *code[0] is that pointer dereferenced. If you already have some string in code[0], then, *code[0] will be first character of that string. The assignment is, therefore, wrong.
Also, "Lucas" is going to be in a read-only parts of the compiled code. You will need to make a copy of "Lucas" using strdup before you assign it to a variable that is of type char *.
You need something like:
code[0] = strdup("Lucas");
Now you can use code[0] to access the whole string. You can use *code[0] to access the first character of that string. You can also use code[0][0] to access the first character of that string.
Related
I'm confused about the way C handles strings and char * vs char[].
char name[10] = "asd";
printf("%p\n%p", &name, &name[0]); //0x7ffed617acd
//0x7ffed617acd
If this code gives the same addresses for both arguments, does it mean that the C compiler takes char arrays (strings) as a pointer to the first char in the array and moves in the memory till it gets the null terminator? Why wouldn't the same happen if we changed the char name[] to char *name? (I know they differ but what makes C take both in a different way?)
I know that arrays can't be assigned after declaration (unless you used something like strcpy, strcat) which is also confusing. Why wouldn't C take them as any other data type? (Something tells me the compiler has a specific addr for it while you can assign char* to whatever location in the mem since its a pointer).
I know that char * have fixed size unlike char[] which makes char * not usable for first argument of strcat.
in C a "string" is an array of type "char" (terminated with \0).
When you are referring to an array in C, you are using a pointer to the first element. In this case (char *).
According to the ANSI-C standard the name of an array is a pointer to the first element.
Being able to write name instead of &name[0] is syntactical sugar.
In the same way accessing an array element writing name[i] is analogue to writing *(name+i).
does it mean that the c compiler takes char arrays (strings) as a pointer to the first char in the array
An array is not a pointer. But an array will implicitly convert to a pointer to first element. Such conversion is called "decaying".
... and moves in the memory till it gets the null terminator???
You can write such loop if you know the pointer is to an element of null terminated string. If you write that loop, then the compiler will produce a program that does such thing.
Why wouldn't the same happen if we changed the char name[] to char *name?
Your premise is faulty. You can iterate an array directly, as well as using a pointer.
If this code gives the same addresses for both arguments, does it mean
The address of an object is the first byte of the object. What this "same address" means is that the first byte of the first element of the array is in the same address as the first byte of the array as a whole.
I know that arrays can't be assigned after declaration (unless you used something like strcpy, strcat) which is also confusing.
Neither strcpy nor strcat assign an array. They assign elements of the array which you can also do without calling those functions.
Why wouldn't C take them as any other data type?
This question is unclear. What do you mean by "C taking them"? Why do you think C should take another data type? Which data type do you think it should take?
char name[10] = "asd";
printf("%p\n%p", &name, &name[0]);
The arguments are of type char(*)[10] and char* respectively. The %p format specifier requires that the argument is of type similar to void* which isn't similar to those arguments. Passing an argument of a type other than required by the format specifier results in undefined behaviour. You should cast other pointer types to void* when using %p.
I am trying to understand why an array variable cannot point anywhere else?
Sample code:
char s[] = "How big is it";
const char *t = s;
This is the code,I create a sample array s[] and assign it a value "How big is it", now I create a character pointer array and assign it the value of s's address.
Now when I say something like this,the complier throws me an error:
s=t; ----> compiler error
Why is that? Is it because the string literal reference would get lost?
= sign has two different meanings in C: initialization and assignment.
When you write char s[]="How big is it";, you initialize a new array with the characters of the string literal including the terminating null.
And the language simply does not allow assignment to an array. It would not make sense anyway because once defined, an array identify a memory location. You can then only assign to array elements or use functions that do that under the hood (memxx, strxx).
It was difficult to title the question.
Essentially I have an array with it's own structure.
typedef struct Video
{
unsigned id;
char title[90];
char producer[60];
}Video;
Video arrayVideo[7];
int main()
{
scanf("%s", arrayVideo[0].title);
printf("%s", arrayVideo[0].title);
}
This code will printout whatever I write during the scanf process.
This small change to int main however;
int main()
{
arrayVideo[0].title[90] = ("Hello");
printf("%s", arrayVideo[0].title);
}
Turns up nothing. The console just outputs the execution time and the normal business. Doesn't output "Hello"
This issues really stems from a confusion about what pointers do in regards to strings. char title[90] is an array of characters that stores 90 chars. title is a pointer to the first element of that array and title[90] is a pointer to one past the end of the array (because array indexing starts at 0, title[89] is the last element)
So if we break down what's going on in this line:
arrayVideo[0].title[90] = ("Hello");
The left hand side is a pointer type, it points to the first element in arrayVideo which is a structure and then within that structure points to the character that's 90 elements past the first element of title, note that this is the 91s element. The right hand side is a string literal of const char* type. Currently this code is just assigning a pointer one past the end of your array to point to the address of the start of the "hello" string literal. It does not copy the contents of the string into your data structure as you would have hoped. I'm slightly surprised you didn't get a warning from your compiler when you compiled this, try compiling with all warnings enabled.
To actually copy the contents of the string correctly you need to use strcpy like so:
strcpy(arrayVideo[0].title,"hello")
Here the destination for the strcpy is the start of your title array and the source is from the const char* string literal "hello".
The second one gives you two warnings which tell you what is going wrong:
t.c: In function ‘main’:
t.c:14:29: warning: assignment makes integer from pointer without a cast [enabled by default]
arrayVideo[0].title[90] = ("Hello");
^
t.c:14:24: warning: array subscript is above array bounds [-Warray-bounds]
arrayVideo[0].title[90] = ("Hello");
^
The first warning tells you that you're trying to store a pointer (to the string "Hello") into a single char of the title array, and the second tells you that its out of bounds anyways, so might do just about anything, though in this case it probably just writes into the first character of the producer array.
Moral: ALWAYS enable all warnings that you can with your compiler, and pay attention to them.
In this example seems that both strings "jesus" are equals(same memory location).
printf("%p\n","jesus");
printf("%p\n","jesus");
Also note that:
printf("%p\n",&"jesus");
printf("%p\n","jesus");
prints the same, but:
char* ptrToString = "jesus";
char* ptrToString = &"jesus"; //ERROR
So i wanna know how an unassigned string is stored in memory and how to point it...
First off, why are "jesus" and &"jesus" the same: "jesus" is an array of type const char[6], and it decays to a pointer to the first element. Taking the address of the array gives you a pointer to an array, whose type is const char (*)[6]. However, the pointer to the array is numerically the same as the pointer to its first element (only the types differ).
This also explains why you have an error in the last line - type type is wrong. You need:
const char (*pj)[6] = &"jesus";
Finally, the question is whether repeated string literals have the same address or not. This is entirely up to the compiler. If it were very naive, it could store a separate copy for each occurrence of a string literal in the source code. If it is slightly cleverer, it'll only store one unique copy for each string literal. String literals are of course stored in memory somewhere, typically in a read-only data segment of the program image. Think of them as statically initialized global variables.
One more thing: Your original code is actually undefined behaviour, since %p expects a void * argument, and not a const char * or a const char (*)[6]. So the correct code is:
printf("%p\n%p\n", (void const *)"jesus", (void const *)&"jesus");
C is a carefully specified language and we can make many observations about your examples that may answer some questions.
Character literals are stored in memory as initialized data. They have type array of char.
They are not necessarily strings because nul bytes can be embedded with \0.
It is not required that identical character string literals be unique, but it's undefined what happens if a program tries to modify one. This effectively allows them to be distinct or "interned" as the implementation sees fit.
In order to make that last line work, you need:
char (*ptrToString)[] = &"jesus"; // now not an ERROR
char *sample = "String Value";
&sample is a pointer to the pointer of "String Value"
is the above statement right?
If the above statement right, what is the equivalent of &sample if my declaration is
char sample[] = "String Value"
In the first one, there are two objects being created.
One is a char * (pointer-to-char) called sample, and the other is an unnamed array of 13 chars containing the characters of the string. In this case, &sample gives the address of the object sample, which is the address of a pointer-to-char - so, a pointer-to-pointer-to-char.
In the second example, there's only one object being created; an array of 13 chars called sample, initialised with the characters of the string. In this case, &sample gives the address of the object sample - so, a pointer-to-array-of-13-chars.
In the second example, there is no "equivalent" to &sample in the first example, in the sense of a pointer-to-pointer-to-char value. This is because there is no pointer-to-char value to take the address of. There is only the array.
While pointers provide enormous power and flexibility to the programmers, they may use cause manufactures if it not properly handled. Consider the following precaustions using pointers to prevent errors. We should make sure that we know where each pointer is pointing in a program. Here are some general observations and common errors that might be useful to remember. *ptr++, *p[],(ptr).member
In the first part &sample will return the address of 'sample' pointer created and in the second case the starting address of the string created as object.
In C arrays and pointers are more or less interchangable. You can treat an array name like it is a pointer, and a pointer like it is an array name.
If you take the address of (&) of a pointer, of course you get a pointer to a pointer.
&sample is the address of the pointer that points to "String Value".
For the second example, since an array name that is not followed by a subscript is interpreted as the pointer to the initial element of the array, which means
sample
and
&sample[0]
are the same, therefore &sample is also the address of the pointer that points to the string.