I'm wondering what the difference is between
char* str[NUM];
char str[NUM];
char* str;
My understanding is that an array definition such as the one in the middle points to the address of the first value, that is str[0]. But I also see the notation represented by the first line of code, that is, a pointer to an array. Are these three equivalent? I'm aware the array definition sets space in the stack for NUM characters so is that probably better than just
char* str?
Thanks
char* str[NUM];
This is an array of NUM char pointers
char str[NUM];
This is an array named str which is NUM chars long.
char *str;
This is a pointer to type char
char* str[NUM];
Declares str as array of num pointers to chars.
char str[NUM];
Declares str as array of num chars.
char* str;
Declares str as pointer to a char.
You can test these type of declarations here.
char* str[NUM];
An Array with NUM elements. Each element is a pointer-to-character(s).
In common terms, this is likely an array of strings.
str[0] is the first string.
str[1] is the second string, etc, etc.
Any element of this array may be NULL.
char str[NUM];
An array with NUM elements. Each element is an individual character.
In common terms, this is a fixed-size string of length NUM-1.(the last position is for the string null-terminator)
This string cannot be NULL. It can be empty (""), but it always exists.
char* str;
A pointer to characters(s).
In common terms, this is a string, of no particular fixed size. You'll find the end of the string when you find the null-terminator.
This string can be NULL, and not point to any memory.
char* str1[NUM]; // an array of size NUM of pointers to char
char str2[NUM]; // an array of size NUM of char
char* str3; // a pointer to char
Uses of these might be:
str1[NUM-1] = strdup("foo");
strcpy(str2, "foo");
str3 = strdup("foo");
Related
Can I consider *str[10] as two dimensional array ?
If I declare char *str[10]={"ONE","TWO","THREE"} how we can access single character ?
This record
char str[10];
is a declaration of an array with 10 elements of the type char, For example you can initialize the array like
char str[10] = "ONE";
This initialization is equivalent to
char str[10] = { 'O', 'N', 'E', '\0' };
all elements of the array that are not explicitly initialized are zero-initialized.
And you may change elements of the array like
str[0] = 'o';
or
strcpy( str, "TWO" );
This record
char *str;
declares a pointer to an object of the type char. You can initialize it for example like
char *str = "ONE";
In this case the pointer will be initialize by the address of the first character of the string literal.
This record
char * str[10];
is a declaration of an array of 10 elements that has the pointer type char *.
You can initialize it as for example
char * str[10] = { "ONE", "TWO", "THREE" };
In this case the first three elements of the array will be initialized by addresses of first characters of the string literals specified explicitly. All other elements will be initialized as null pointers.
You may not change the string literals pointed to by elements of the array. Any attempt to change a string literal results in undefined behavior.
To access elements of the string literals using the array you can use for example two subscript operator. For example
for ( sisze_t i = 0; str[0][i] != '\0'; ++i )
{
putchar( str[0][i] );
}
putchar( '\n' );
If you want to change strings then you need to declare for example a two dimensional array like
char str[][10] = { "ONE", "TWO", "THREE" };
In this case you can change elements of the array that are in turn one-dimensional arrays as for example
str[0][0] = 'o';
or
strcpy( str[0], "FOUR" );
Yes: char* str[10]; would create an array of 10 pointers to chars.
To access a single character, we can access it like a 2 dimensional array; i.e.:
char* str[10]={"ONE","TWO","THREE"};
char first = str[0][0];
Can I consider *str[10] as two dimensional array ?
It's unclear what you mean. *str[10] is not a valid type name, and the context is a bit lacking to determine how else to interpret it.
If you mean it as an expression referencing the subsequent definition then no, its type is char, but evaluating it produces undefined behavior.
If you are asking about the type of the object identified by str, referencing the subsequent definition, then again no. In this case it is a one-dimensional array of pointers to char.
If I declare char *str[10]={"ONE","TWO","THREE"} how we can access single character ?
You can access one of the pointers by indexing str, among other other ways. For example, str[1]. You can access one of the characters in the string into which that pointer points by using the indexing operator again, among other ways. For example, str[1][0]. That you are then using a double index does not make str a 2D array. The memory layout is quite different than if you declared, say, char str[3][10];.
I read a few similar questions, C: differences between char pointer and array, What is the difference between char s[] and char *s?, What is the difference between char array[] and char *array? but none of them seem to clear my doubt.
I'm aware that
char *s = "Hello world";
makes the string immutable whereas
char s[] = "Hello world";
can be modified.
My doubt is if I do char stringA[LEN]; and char* stringB[LEN]; Are they any different? Or does stringB again becomes immutable as in the case before?
Let me give you a visual explanation:
As you can see, a is an array of 4 characters, whereas b is an array of 4 character pointers, each pointing to the beginning of a C string. Each one of those strings can have a different length.
Are they any different?
Yes.
Both variables stringA and stringB are arrays. stringA is an array of char of size LEN and stringB is an array of char * of size LEN.
char and char * are two different types. stringA can hold only one character string of length LEN while elements of stingB can point to LEN number of strings.
Or does stringB again becomes immutable as in the case before?
Whether strings pointed by elements of stringB is mutable or not will depend on how memory is allocated. If they are initialized with string literals
char* stringB[LEN] = { "Apple", "Bapple", "Capple"};
then they are immutable. In case of
for(int i = 0; i < LEN; i++)
stringB[i] = malloc(30) // Allocating 30 bytes for each element
strcpy(stringB[0], "Apple");
strcpy(stringB[1], "Bapple");
strcpy(stringB[2], "Capple");
they are mutable.
They are not the same.
Here stringA is an array of char, that means printing stringA[0] will show the letter S:
char stringA[] = "Something";
Whereas printing stringB[0] here will show Something (array of pointer to char):
char* stringB[] = { "Something", "Else" };
They are not having the same datatype, less being comparable.
char stringA[LEN]; is a char array of LEN length. (Array of chars)
char* stringB[LEN]; is a char * array of LEN length. (Array of char pointers)
FWIW, in case of char *s = "Hello world"; s is a pointer which points to a string literal which is non-modifiable. The pointer itself can certainly be changed. Only the content it points to (values) cannot be changed.
The reason
char* s = "Hello World!";
is immutable is because "Hello World!" is stored in RO(Read Only) memory, sow hen you try to change it, it throws an error. Declaring it as a pointer to the first element of an "array" is NOT the reason it's immutable. You seem to be slightly confused as well. Assuming your questions is exactly what you mean,
char stringA[LEN] = "ABC";
is a string in traditional C style, but stringB as you've defined isn't a string, it's an array of strings -
char* stringB[LEN] = {"ABC", "DEF"};
Assuming you mean what I think you mean,
char stringA[LEN] = "Hello World!";
char *stringB = malloc(LEN);
strcpy(stringB, stringA);
In this case, stringB IS mutable, since it refers to writable memory.
I am writing a simple function in C that should build a char array from string "abc" – so it should build {'a','b','c'} – and return a pointer to that array. Here is my code for this function:
char * makeArr()
{
static char arr[3];
sprintf(arr, "%s\n", "abc");
return arr;
}
Problems occur when I call this method in main:
int main(int argc, char *argv[])
{
char *arr[3];
arr = makeArr();
return 0;
}
The compiler is complaining about casting / conflicting types. I've been playing with pointers, casting and dereferencing for quite a while now, but can't seem to get it to work. Please let me know where my logic is wrong.
Hmm ... there are several errors in this code. Let's start with the most obvious your compiler complains about:
char *arr[3];
This line declares arr to be an array of three pointers to char. What you return from your function is a single pointer to a char -> doesn't match.
Next:
static char arr[3];
sprintf(arr, "%s\n", "abc")
Here you reserve 3 chars. the sprintf() will write 5 chars. %s is replaced by the 3 characters in your string literal "abc". You add a newline character and then a 0 is added as the marker for the end of the "string". Makes 5. This btw is undefined behavior. You write past the end of your array. Code like this can be compiled, but there's no guarantee at all about what will happen at runtime.
Doing a cut here. You should read about arrays and pointers in C. If the text you're reading claims they are the same ... stop right there and find a better text. They aren't.
I'll try to explain this here briefly, so it's suitable for the Q&A style.
An array in C indeed is a contiguous space of several values. char arr[3] means a variable that holds 3 chars.
On the other hand, a char * is just a pointer pointing to a char -- this could be the first element of an array.
In C, you can't pass arrays as function parameters, and you can't return arrays from a function. Trying to do so leads to an implicit conversion: What is actually passed is a pointer to the first element of that array.
I think the last bit of information missing is what a string literal in C is: it's an array (anonymous, e.g., it doesn't have a name) containing all the characters in the double quotes plus a 0 appended. The 0 marks the end of a "string" in C.
In an expression, a string literal evaluates to a pointer to the first element.
So, something like this:
char *foo = "bar";
will lead to foo pointing to the b of the array. It's like writing
static const char no_name_0[] = { 'b', 'a', 'r', 0 };
char *foo = &(no_name_0[0]);
Among other things, you confused:
char arr[3]; // array of 3 chars.
and,
char *arr[3]; // array of 3 pointers to char.
In main(), you should only write char *arr;
Firstly, char arr[3]; is too snall to store "abc\n". It must have at least 5 elements including terminating null-character.
Then, char *arr[3]; is a 3-element array of char*.
You should assign makeArr()'s return value (it has char* type) to arr[0] or another element, or you should change the type of arr in main function to char*, which is the same type as makeArr()'s return value.
Moreover, this makeArr() doesn't make any array and returns (a pointer to) the existing array. Yoy should use malloc() to "make an array".
UPDATE:
Assigning a value of char* to the array char arr[10]; seems invalid in C.
You should use strcpy() or strncpy() (safer than strcpy()) to copy the string stored in the array between arrays.
Pass the array as an argument and modify it in the called function, would be easier. If you're statically creating the array and there's no need to allocate memory, don't, just pass around your pointers to the functions to be modified by reference
void makeArr(char arr[]){
sprintf(arr, "%s\n", "abc");
}
Simply pass the existing declared array to the makeArr function...
int main(int argc, char *argv[]) {
char arr[10];
makeArr(arr);
return 0;
}
You couldn't assign the result of makeArr to arr. I guess that's your casting error. Oversimplifying, arr points to the place on the stack where the array of 10 characters is allocated. So, I'd pass in arr to makeArr as a char*. So, you'd end up with something like this:
#include <stdio.h>
char * makeArr(char *arr)
{
sprintf(arr, "%s\n", "abc");
return arr;
}
int main(int argc, char *argv[])
{
char arr[10];
makeArr(arr);
printf("%s\n", arr);
return 0;
}
This code doesn't work.
char* randomWordHidden[length];
char try;
printf("Enter a letter: ");
scanf(" %c", &try);
//here there is a loop
randomWordHidden[i] = try; //assign position of randomWordHidden with try value
it gives error: [Warning] assignment makes pointer from integer without a cast
But I do this and it works:
randomWordHidden[i] = "H";
How can i assign to a position of randomWordHidden the value of try var?
Well;
you have made a list (of length length) of pointers to characters. I guess what you want is:
char randomWordHidden[length];
that should be length characters.
Your randomWordHidden is not an array of char, but an array of char*, so effectively an array of strings. That's why assigning a char gives you a warning, because you cannot do char* = char. But the assignment of "H", works, because it is NOT a char - it is a string (const char*), which consists of letter 'H' followed by terminating character '\0'. This is char - 'H', this is string (char array) - "H".
You most likely need to change the declaration of the randomWordHidden array to char instead of char*.
I believe arrays are already pointers, no need for that declaration.
char randomWordHidden[length];
Give that a try?
Here is my code:
printf("%s\n", "test1");
char c = '2';
char * lines[2];
char * tmp1 = lines[0];
*tmp1 = c;
printf("%s\n", "test2");
I don't see the second printf in console.
Question: Can anybody explain me what's wrong with my code?
NOTE: I'm trying to learn C :)
This line:
char * lines[2];
declares an array of two char pointers. However, you don't actually initialize the pointers to anything. So later when you do *tmp1 = (char)c; then you assign the character c to somewhere in memory, possibly even address zero (i.e. NULL) which is a bad thing.
The solution is to either create the array as an array of arrays, like
char lines[2][30];
This declares lines to have two arrays of 30 characters each, and since strings needs a special terminator character you can have string of up to 29 characters in them.
The second solution is to dynamically allocate memory for the strings:
char *lines[2];
lines[0] = malloc(30);
lines[1] = malloc(30);
Essentially this does the same as the above array-of-arrays declaration, but allocates the memory on the heap.
Of course, maybe you just wanted a single string of a single character (plus the terminator), then you were almost right, just remove the asterisk:
char line[2]; /* Array of two characters, or a string of length one */
The array lines in uninitialized. Thus lines[0] is an uninitalized pointer. Dereferencing it in *tmp1 is sheer undefined behaviour.
Here's an alternative, that may or may not correspond to what you want:
char lines[2];
char * tmp1 = lines; // or "&lines[0]"
*tmp = c;
Or, more easily:
char lines[2] = { c, 0 };
lines is uninitialized, and tmp1 initialization is wrong.
It should be:
char lines[2];
char * tmp1 = lines;
Alternatively, you can say:
char * tmp1 = &lines[0];
Or else for an array of strings:
char lines[2][30];
char * tmp1 = lines[0];
The line
char * lines[2];
creates an array of two char pointers. But that doesn't allocate memory, it's just a "handle" or "name" for the pointer in memory. The pointer doesn't point to something useful.
You will either have to allocate memory using malloc():
char * lines = malloc(2);
or tell the compiler to allocate memory for you:
char lines[2];
Note: Don't forget to terminate the string with a 0 byte before you use it.
char *lines[2]; : A two element array of char pointers.
char *tmp; : A pointer to a character.
char *tmp = lines[0] : The value inside the array element 0 of the lines array is transferred into tmp. Because it is an automatic array, therefore it will have garbage as the value for lines[0].
*temp : Dereference the garbage value. Undefined Behaviour.
char * tmp1 = lines[0];
here you declare a char pointer and initialize its pointer value to line[0],the fist element stored in line array which is also uninitialized.
now the tmp is pointing to somewhere unknown and not actually accessible. When you
*tmp1 = (char)c;
you are operating on a invalid memory address which causes a Segmentation fault.