Why cannot an array variable point anywhere else? - c

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).

Related

C - Convert int to char

I am looking for a solution for my problem (newbie here).
I have an array of strings (char** arrayNum) and I would like to store the number of elements of that array at the first index.
But I can't find the right way to do convert the number of elements as a string (or character).
I have tried itoa, casting (char), +'0', snprintf ... nothing works.
As every time I ask a question on Stack Overflow, I am sure the solution will be obvious. Thanks in advance for your help.
So I have an array of strings char** arrayNum which I populate, leaving the index 0 empty.
When I try to assign a string to arrayNum[0]:
This works: arrayNum[0] = "blabla";
This does not work: arrayNum[0] = (char) ((arraySize - 1)+'0');
I have tried countless others combinations, I don't even remember...
arrayNum can be thought of as an array of strings (char *). So you will naturally have trouble trying to assign a char (or indeed any type other than char *) to an element of this array.
I think it would preferable to store the length of the array separately to the array. For example, using a struct. To do otherwise invites confusion.
If you really, really want to store the length in the first element, then you could do something like:
arrayNum[0] = malloc(sizeof(char));
arrayNum[0][0] = (char) ((arraySize - 1)+'0');
This takes advantage of the fact that arrayNum is strictly an array of pointers and each of those pointers is a pointer to a char. So it can point to a single character or an array of characters (a "string").
Compare this for clarity with (say):
struct elements {
int length;
char **data;
};
arrayNum is not an "array of strings."
It might be useful for you to think about it that way, but it is important for you to know what it really is. It is an array of pointers where each pointer is a pointer to char.
Sometimes a pointer to char is a "string," and sometimes it's a pointer into the middle of a string, and sometimes it's just a pointer to some character somewhere. It all depends on how you use it.
The C programming language does not really have strings. It has string literals, but a string literal is just a const array of characters that happens to end with a \000. The reason you can write arrayNum[0] = "blabla"; is because the value of the string literal "blabla" is a pointer to the first 'b' in "blabla", and the elements of the arrayNum array are pointers to characters.
It's your responsibility to decide whether arrayNum[i] points to the first character of some string, or whether it just happens to point to some single character; and it's your responsibility to decide and keep track of whether it points to something that needs to be freed() or whether it points to read-only memory, or whether it points to something on the stack, or whether it points to/into some staticly allocated data structure.
The language doesn't care.

why can't I put an array name on the left side of an equals sign [duplicate]

This question already has answers here:
Why canĀ“t we assign a new string to an char array, but to a pointer?
(4 answers)
Closed 9 years ago.
Why can't we do this in c:
char name[6];
name = "Jason";
However, with pointers we can.
char name;
char * pName = &name;
pName = "Jason";
What is the major difference between arrays and pointers ? I understand that the array is a fixed constant pointer, fair enough but I'm not quite sure about how this works if the name of an array is a pointer(pointer constant) which points to the first element in the array why can't I change the content of the elements of that array with an equal sign? I answered my question by saying it is a pointer constant but I don't grasp this concept!
Because when you write "a constant string", the compiler allocates this string in the compiled code and if you do c = "a string" where c is a pointer, c will now point to that particular location.
The position of an array instead is fixed (you cannot say "now point to something else"), so you should copy the string with strcpy.
strcpy(name, "Jason");
In this way the compiler will allocate "Jason" in the compiled code, but at execution time its content will be copied in the memory area dedicated to name.
Simply put, an array name is effectively a constant pointer to the array.
Since a constant object cannot be modified during execution, specifying an array as a lvalue i.e. to the left of an assignment operator is invalid.
To use your example, the following is the equivalent of trying to assigning something to a array name :
char name;
const char *pName = &name;
pName = "Jason"; //error!!
Checkout memcpy(), strcpy() to modify contents of an arrays. Take care to ensure that the arrays being written-to aren't constant (or statically allocated).
C never copies bare strings (the actual character data) around as a result of evaluating the = assignment operator. This is because such a thing is not considered "a value" in C. You can embed an array into a struct to make it a value, as pointed out in a comment.
Your first example would only make sense if it did, but it doesn't. The second example just assigns a pointer value, which is fine. But you cannot re-assign the address of an array (name is a constant pointer in the first example) so there's no way to make it work.
Also, remember that there are more arrays than character arrays, it would be weird to have that much special behavior overloaded on the = operator for character arrays, in my opinion.

Pointers to strings

I am a newbie to C programming. And I am confused with the chaotic behavior of pointers. Specially when it comes to strings and arrays.
I know that I can't write like,
#include <stdio.h>
int main()
{
int *number=5;
printf("%d",*number);
}
Because clearly it will try to write to the 5th location of the memory.And that will crash the program.I have to initialize the "number".
But when it comes to strings I can write like,
#include <stdio.h>
int main()
{
char *name="xxxxx";
printf(name);
}
And it works too. So that means it implicitly initialize the "name" pointer.I also know that name=&name[0] But I have found that name=&name too. How can it be?
Because, to me it looks two variables with the same name. Can anybody tell me how strings are created in memory?(All this time time I assumed it creates name[0].....name[n-1] and another variable(a pointer) called "name", inside that we put the location of name[0].Seem to be I was wrong.)
PS:-My English may not be good and if somebody can give me a link regarding above matter that would be grateful.
C, like many programming languages, supports the concept of "literals" - special syntax that, when encountered, causes the compiler to create a value in a special way.
-2, for example, is an integer literal. When encountered, the compiler will treat it as a value of type int with the content of -2. "..." is a string literal - when encountered, the compiler allocates new space in a special memory area, fills it with data that corresponds to the chars you used inside the literal, adds a 0 at the end of that area, and finally uses a pointer to that area, of type char*, as the result of the literal expression. So char* s = "hello" is an assignment from something of type char* into a variable of type char* - completely legal.
You sneaked in another question here - why a == &a[0]. It's best to ask one question at a time, but the gist of it is that a[n] is identical to *((a)+(n)), and so:
&a[0] == &*(a+0) == a+0 == a
char *name="xxxxx";
This creates a char array(const) in memory, and it will assign the address of 1st element of it to name. char* array names are like pointers. &name[0] means address of 1st element and name (In c,cpp just the char * array name will provide you with the address of 1st element too (bcos that is what was assigned to name in the 1st place itself)) also gives the same result.
The notation name[i] is translated as *(name+i) so u actually have a base address name to which you add subscripts. (calculations are as per pointer arithmetic) . printf("%s", name) is designed to print from start address to \0 (which is appended to the end of strings created using char* a.k.a String literals)
Check this too.
That is because you those strings are actually arrays of characters. What you do with the line char *name = "xxxxx";: You construct an array of 6 character values (5 of them being 'x' and the last one being '\0'). name is a pointer to that array.
That's how strings are normally handles in C, you have some kind of sequence of characters, terminated with a '\0' character, to tell functions like printf where to stop processing the string.
Let's consider this piece of code:
char *name="xxxxx";
What happens here is that the string xxxxx is allocated memory and a pointer to that memory location,or the address of that string is passed to the pointer variable name.Or in other words you initialize name with that address.
And printf() is a variadic function (one that takes one fixed argument followed by a random number of arguments).The first argument to printf() is of type const char*.And the string identifier name when passed as an argument denotes the base address of that string.Hence you can use
printf(name);
It will simply output xxxxx
name=&name too. How can it be?--Well that's a justified question.
Let me explain first with a real-world analogy. Suppose you have the first house in a row of houses in a housing society.Suppose it's plot number 0.The other houses are on plots 1,2,3......Now suppose there is a pointer to your house, and there is another pointer to the whole housing society's row. Won't the two pointers have the same address, which will be plot 0?This is because a pointer signifies a single memory location.It's the type of the pointer that matters here.
Bringing this analogy to the string( array of characters), the name identifier only signifies the base address of the string, the address of its first character (Like the address of the first house).It is numerically same to the address of the whole string,which is (&name),which in my analogy is the ROW of houses.But they are of different types, one is of type char* and the other is of type char**.
Basicly what happens when the C-compiler see the expression
char *name = "xxxxx";
is, it will say. Hey "xxxxx" that's a constant string (which is an array of bytes terminated with a 0 byte), and put that in the resulting programs binary. Then it will substitute the string for the memory location, sort of like:
char *name = _some_secret_name_the_compiler_only_know;
where _some_secret_name_the_compiler_only_know is a pointer to the memory location where the string will live once the program gets executed. And get in with parsing the file.

How an unassigned string is stored in memory and how to reference it?

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

Why is literal string assignment in C not possible for array with specified length? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Do these statements about pointers have the same effect?
All this time I thought that whenever I need to copy a string(either literal or in a variable) I need to use strcpy(). However I recently found out this:
char a[]="test";
and this
char *a="test";
From what I understand the second type is unsafe and will print garbage in some cases. Is that correct? What made me even more curious is why the following doesn't work:
char a[5];
a="test";
or this
char a[];
a="test";
but this works however
char *a;
a="test";
I would be greatful if someone could clear up things a bit.
char a[]="test";
This declares and initializes an array of size 5 with the contents of "test".
char *a="test";
This declares and initializes a pointer to the literal "test". Attempting to modify a literal through a is undefined behavior (and probably results in the garbage you are seeing). It's not unsafe, it just can't be modified since literals are immutable.
char a[5];
a="test";
This fails even when both a and "test" have the exact same type, just as any other attempt to copy arrays thorugh assignment.
char a[];
a="test";
This declares an array of unknown size. The declaration should be completed before being used.
char *a;
a="test";
This works just fine since "test" decays to a pointer to the literal's first element. Attempting to modify its contents is still undefined behavior.
Let's examine case by case:
char a[]="test";
This tells the compiler to allocate 5 bytes on the stack, put 't' 'e' 's' 't' and '\0' on it. Then the variable a points to where 't' was written and you have a pointer pointing to a valid location with 5 available spaces. (That is if you view a as a pointer. In truth, the compiler still treats a as a single custom type that consists of 5 chars. In an extreme case, you can imagine it something like struct { char a, b, c, d, e; } a;)
char *a="test";
"test" (which like I said is basically 't' 'e' 's' 't' and '\0') is stored somewhere in your program, say a "literal's area", and a is pointing to it. That area is not yours to modify but only to read. a by itself doesn't have any specific memory (I am not talking about the 4/8 bytes of pointer value).
char a[5];
a = "test";
You are telling the compiler to copy the contents of one string over to another one. This is not a simple operation. In the case of char a[] = "test"; it was rather simple because it was just 5 pushes on the stack. In this case however it is a loop that needs to copy 1 by 1.
Defining char a[];, well I don't think that's even possible, is it? You are asking for a to be an array of a size that would be determined when initialized. When there is no initialization, it's just doesn't make sense.
char *a;
a = "test";
You are defining a as a pointer to arrays of char. When you assign it to "test", a just points to it, it doesn't have any specific memory for it though, exactly like the case of char *a = "test";
Like I said, assigning arrays (whether null-terminated arrays of char (string) or any other array) is a non-trivial task that the compiler doesn't do for you, that is why you have functions for it.
Do not confuse assignment and initialisation in C, they are different.
In C a string is not a data type, it is a convention, utilising an array and a nul terminator. Like any array, when you assign it, it's name resolves as a mere pointer. You can assign a pointer, but that is not the same as assigning a string.

Resources