Why does char* create a string? - c

I'm confused as to why I can create a string by using just char*. Isn't a char* just a pointer to a single char? What makes me suddenly allowed to treat this thing as a string? Can I do this with other objects? What about:
int* arr;
Do I now have an array of ints? Is it dynamically sized? Can I just start calling
arr[0] and arr[1]
and expect it to work?
I've been googling for quite awhile now, and can't find any clear answer to this question.
This is one part of C I've always just accepted as the way it works...no more.

Pointers point to things. int *arr; currently does not point anywhere. You cannot treat it as pointing to anything (array or otherwise).
You can point it at something. If you point it at a single int, you can treat it as pointing to a single int. If you point it at an element of an array of ints, you can treat it as pointing to an element of an array.
char behaves the same as int (or any other object type) in this respect. You can only treat a char * as pointing to a string if you first point that char * to a string.

Isn't a char* just a pointer to a single char?
It is a pointer to a memory location that should hold a char. It can be a single allocated char, or an array of several char's.
What makes me suddenly allowed to treat this thing as a string?
When the char* pointer points to a memory location where several chars[] are allocated one after another (an array), then you can access them with an array index [idx]. But you have to either:
A. Use a statically allocated array in code:
char myArray[5];
B. or Dynamic allocation (malloc() in C language):
int chars_in_my_array = 10;
char* myArray = (char*)malloc( sizeof(char) * chars_in_my_array );
Can I do this with other objects? What about: int* arr; Do I now have an array of ints?
no you don't:
int* p; //'p' is a *pointer* to an int
int arr[10]; //'arr' is an array of 10 integers in memory.
You can set 'p' to point to the first element in 'arr' by doing this:
p = &arr[0]; //'p' points to the address of the first item in arr[]
Is it dynamically sized?
No. That's something you'd see in a higher-level construct like 'std::string' in C++, or 'String' in Java. In C, memory is managed manually (or you use existing library functions to do this for you. see the standard header file 'string.h')
Can I just start calling arr[0] and arr[1] and expect it to work?
Not unless you do this:
int arr[5];
arr[0] = 100; arr[1] = 200;
...Because you statically allocate an array of five integers. Then you can access them with an array subscript.
However you can NOT do this:
int* p;
p[0] = 100; p[1] = 200; // NO!!
Because 'p' is just a variable that contains a memory address to an integer. It doesn't actually allocate any memory unless you explicitly allocate memory for it. You can do this though:
int* p;
int arr[10];
p = &arr[0];
p[0] = 100; p[1] = 200; // This is OK
This works because 'p' now points to memory that has been (statically) allocated for an array. So we can access the array through the pointer 'p'.
You can also dynamically allocate the array:
int* p;
p = (int*)malloc( sizeof(int) * 10 );
if( p != NULL ) {
p[0] = 100;
p[1] = 200;
}
Here we allocate memory for 10 integers and 'p' points to the first item. Now we can use 'p' as an array. But only for 10 items maximum!
I've been googling for quite awhile now, and can't find any clear
answer to this question. This is one part of C I've always just
accepted as the way it works...no more.
Really? Try googling 'arrays in c', 'memory allocation in C', 'static vs dynamic allocation C', and functions such as malloc() and free(). There's a plethora of information available, but hope this helps for starters :)

Related

**array vs array[][]: are they both 2D arrays?

My teacher told me that int **array is not a 2D array, it is just a pointer to a pointer to an integer.
Now, in one of my projects I have to dynamically allocate a 2D array of structs, and this is how it is done:
struct cell **array2d = (struct x **)calloc(rows, sizeof(struct x *));
for (int i = 0; i < columns; i++) {
array2d[i] = (struct x *)calloc(j, sizeof(struct x));
}
But here we return a pointer to a pointer to the struct, so how is this a 2D array?
Before using dynamic allocation, I had a statically allocated array of the form:
array2d[][]
Now that I replaced it by dynamic allocation, I also replaced array2d[][] by **array2d.
Every function that takes array2d[i][j] als argument now returns an error saying the types don't match.
Could someone explain me what is happening here? What is the difference between **array and array[m][n] and why is the compiler complaining?
They're thoroughly different things.
An array is a sequence of values of the same type stored one after another in memory.
In C, an array is more or less interchangeable with a pointer to its first element — a[0] is *a,
a[1] is *(a+1), etc. — at least when we're talking about one-dimensional arrays.
But now consider:
int a[3][3];
in this case, a contains nine elements, contiguous in memory. a[0][0] through a[0][2], then a[1][0] immediately after, up until a[2][2].
If you pass a to a function, it would fit into a parameter type of int * or int[3][3] or int [][3] (knowing the "stride" of the second dimension is absolutely necessary to doing the math to look up a given element).
On the other hand:
int *b[3];
b[0] = malloc(...);
b[1] = malloc(...);
b[2] = malloc(...);
in this case, b is an array of 3 elements, each of which is a pointer to an array of 3 elements. You still access it like b[0]0] or b[1][2], but something completely different is happening under the hood. The elements aren't all stored contiguously in memory, and *b isn't any of them, it's a pointer. If we were to pass b to a function, we would receive it with a parameter of type int ** or int *[]. Knowing the length of each row in advance isn't necessary, and in fact each row could have a different length from the others. Some of the rows could even be null pointers, with no storage behind them for integers.

Are there differences between int pointer and char pointer in c?

I'm new to C and have a trouble understanding pointers. The part that I'm confused is about char * and int *.
For example, we can directly assign a pointer for char, like
char *c = "c"; and it doesn't make errors.
However, if I assign a pointer for int like I just did, for example int * a = 10;,
it makes errors. I need to make an additional space in memory to assign a pointer for int,
like int *b = malloc(sizeof(int)); *b = 20; free(b);...
Can anyone tell me why?
I think you're misunderstanding what a pointer is and what it means. In this case:
int* a = 10;
You're saying "create a pointer (to an int) and aim it at the literal memory location 0x0000000A (10).
That's not the same as this:
int n = 10;
int* a = &n;
Which is "create a pointer (to an int) and aim it at the memory location of n.
If you want to dynamically allocate this:
int* a = malloc(sizeof(int));
*a = 10;
Which translates to "create a pointer (to an int) and aim it at the block of memory just allocated, then assign to that location the value 10.
Normally you'd never allocate a single int, you'd allocate a bunch of them for an array, in which case you'd refer to it as a[0] through a[n-1] for an array of size n. In C *(x + y) is generally the same as x[y] or in other words *(x + 0) is either just *x or x[0].
In your example, you do not send c to the char 'c'. You used "c" which is a string-literal.
For string-literals it works as explained in https://stackoverflow.com/a/12795948/5280183.
In initialization the right-hand side (RHS) expression must be of or convertible to the type of the variable declared.
If you do
char *cp = ...
int *ip = ...
then what is in ... must be convertible to a pointer to a char or a pointer to an int. Also remember that a char is a single character.
Now, "abc" is special syntax in C - a string literal, for creating an array of (many) immutable characters. It has the type char [size] where size is the number of characters in the literal plus one for the terminating null character. So "c" has type char [2]. It is not char. An array in C is implicitly converted to pointer to the first element, having then the type "pointer to the element type". I.e. "c" of type char [2] in char *cp = "c"; is implicitly converted to type char *, which points to the first of the two characters c and \0 in the two-character array. It is also handily of type char * and now we have char *cp = (something that has type char * after conversions);.
As for int *, you're trying to pass an integer value to a pointer. It does not make sense.
A pointer holds an address. If you'd ask for the address of Sherlock Holmes, the answer would be 221 Baker Street. Now instead what you've done is "address of Sherlock Holmes is this photo I took of him in this morning".
The same incorrect code written for char * would be
char *cp = 'c'; // or more precisely `char *p = (char)'c';
and it would give you precisely the same error proving that char *cp and int *cp work alike.
Unfortunately C does not have int string literals nor literals for integer arrays, though from C99 onwards you could write:
int *ip = (int[]){ 5 };
or
const int *ip = (const int[]){ 5 };
Likewise you can always point a char * or int * to a single object of that type:
char a = 'c';
char *pa = &a;
int b = 42;
int *pb = &b;
now we can say that a and *pa designate the same char object a, and likewise b and *pb designate the same int object b. If you change *pa you will change a and vice versa; and likewise for b and *pb.
A string literal like "c" is actually an array expression (the type of "c" is "2-element array of char).
Unless it is the operand of the sizeof or & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "array of T" will be converted, or "decay" to an expression of type "pointer to T" and its value will be the address of the first element of the array.
So when you write
char *c = "c";
it’s roughly equivalent to writing
char string[] = "c";
char *c = &string[0];
You’re assigning a pointer to a pointer, so the compiler doesn’t complain.
However, when you write
int *a = 10;
you’re assigning an int value to a pointer and the types are not compatible, so the compiler complains. Pointers are not integers; they may have an integer representation, but that’s not guaranteed, and it won’t be the same size as int.
Are there differences between int pointer and char pointer in c?
short answer: NO
All pointers in C are created equal in the last decades. During some time there were pointers of different sizes, in some platforms like Windows, due to a thing called memory model.
Today the compiler sets the code to use 32-bit or 64 or any size pointers depending on the platform, but once set all pointers are equal.
What is not equal is the thing a pointer points to, and it is that you are confused about.
consider a void* pointer. malloc() allocates memory in C. It always return a void* pointer and you then cast it to anything you need
sizeof(void*) is the same as sizeof(int*). And is the same as sizeof(GiantStruct*) and in a 64-bit compiler is 8 bytes or 64 bits
what about char* c = "c"?
you must ask yourself what is "c". is is char[2]. And it is a string literal. Somewhere in memory the system will allocate an area of at least 2 bytes, put a 'c' and a zero there, since string literals are NULL terminated in C, take that address in put in the address allocated to your pointer c.
what about int* a = 10?
it is the same thing. It is somewhat ok until the operating system comes in. What is a? a is int* pointer to an int. And what is *a? an int. At which address? 10. Well, truth is the system will not let you access that address just because you set a pointer to point to it. In the '80s you could. Today there are very strong rules on this: you can only access memory allocated to your processes. Only. So the system aborts your program as soon as you try to access.
an example
if you write
int* a = malloc(300);
the system will allocate a 300-bytes area, take the area address and write it for you at the address allocated to a. When you write *a=3456 the system will write this value to the first sizeof(int) bytes at that address.
You can for sure write over all 300, but you must somewhat manipulate the pointer to point inside the area. Only inside that area.
In fact C language was designed just for that.
Let us write "c" to the end of that 300-byte area alocated to a:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* c = "c";
int* a = (int*)malloc(300);
*a = 3456;
printf("Area content is %d\n", *a);
char* pToEnd = (char*)a + 298;
*(pToEnd) = 'c';
*(pToEnd + 1) = 0;
printf("At the end of the 300-byte area? [Should be 'c'] '%s'\n", pToEnd);
printf("The pointer c points to '%s'\n", c);
//*c = 'x'; // error: cancel program
c = pToEnd;
printf("The pointer c now points do the end of the 300-byte area:'%s'\n", c);
free(a);
return 0;
};
and see
Area content is 3456
At the end of the 300-byte area? [Should be 'c'] 'c'
The pointer c points to 'c'
The pointer c now points do the end of the 300-byte area:'c'
Also note that as soon as you try to write over c, the char pointer in your example, your program will also cancel. It is a read only area --- see the comment on line 14. But you can point c inside the area in the example and use it, since the pointer in itself is not constant.
And when you write c = pToEnd in the example above access to the string literal is lost forever. In some sense is a memory leak, but it is a static allocated area. The leak is not the area but the address.
Note also that free(a) at the end, even if being a int* will free all 300 bytes
The direct answer to your question, is that, C language is a strict typed language. And before the machine code is produced, a compiler checks for some possible errors. The types are different, and that is all that the compiler wants to know.
But from the bit-byte point of view, there are no difference, for C language, with the above two pointers.
Take a look at your code with online compiler
void main(){
int * a = 10; /* <= this presumably gives you an error. */
}
What I did is copy pasted your code that gives you the error. And online compiler had emitted a warning, not an error. Even more than that. Change the C standard to be of c17 and you still get a mere warning.
The note about assigning a string literal to a pointer had been discussed broadly at SO. It deserves a different topic.
To sum it up. For the C language there is no meaningful difference in the above two pointers. It is a user, who takes a responsibility to know a layout of a memory in his/her program. All in all, the language was designed as a high level tool that operates over linear memory.

How do array pointers work in C and how to change pointers

I'm very new to C and I have trouble understanding array pointers. I'm trying to make a array bigger,I copy all of its element to new bigger array but I can't make original variable to point the new array. I'm use to C# where you can do
double[] array1 = new double[5];
double[] array2 = new double[10];
array1 = array2;
I did something similar using int array
int array1 [5];
int array2 [10];
*array1 = &array2;
and it compile but crash the program. Same lines but double or char[] (I was told to use char[] instead of sting in C) do not even compile
[Error] incompatible types when assigning to type 'double' from type 'double (*)[(sizetype)(newsize)]'
The results I found on the topic told me to use double* array1 for variable type but this change the interactions with that variable.
If someone can explain the concept to me or at least tell me what to search for that will be huge help.
I do know the basics of pointers!
There are a few things you need to know about arrays (and pointers):
The first is that arrays and pointers are two different things;
The second is that an array can decay to a pointer to its first element. So if you use array1 (from your example) when a pointer is expected, that's the same as doing &array1[0]. The type of such a pointer is a pointer to a single element type (so for array1 the type will be int *);
The third thing is that for any array of pointer a and index i, the expression a[i] is exactly equal to *(a + i). That means *array1 (again from your example) is the same as array1[0] (*array1 is equal to *(array1 + 0) which is equal to array1[0]);
An array will have a fixed size. Once defined the size of an array can't change;
Lastly when you get a pointer to an array (as in &array2) then you get a pointer to the actual array, not to one of its elements. The type of e.g. &array2 is int (*)[10].
Now we can puzzle together the statement
*array1 = &array2;
If we do the array-indexing replacement for *array1 then we get
array[0] = &array2;
And here we can see a big problem: The type of a single element of array1 is a plain int. So what the assignment is trying to do is to assign a pointer to an array (of type int (*)[10]) to a single int.
If you want to copy all the elements from one array to another, then use the memcpy function. You're not allowed to assign between arrays.
But beware of the different sizes for array1 and array2. If you go out of bounds of an array (or other allocated memory) you will have undefined behavior.
In C there is no way to make an array variable "reference" a different variable. If you need to use "references" they can be emulated using pointers:
int *pointer1 = array1; // array1 here will decay to &array[0]
int *pointer2 = array2; // Same here for array2
With the above definition pointer1 is (in a way) "referencing" array1. You can now use pointer1 and array1 almost interchangeably.
One major difference between using pointers and arrays is how their sizes are calculated: When you do sizeof on an array you get the size (in bytes) of the whole array. Assuming 32-bit int (the most common) then sizeof array1 will return 5 * 4 (or 20) as the size. If you get the size of a pointer, you get the size of the pointer itself, not what it might point to. So sizeof pointer1 will return either 4 or 8 (depending on if you're in a 32-bit or 64-bit system).
Going back to references, we can now change where pointer1 is pointing:
pointer1 = pointer2; // Assuming pointer2 is unchanged, equivalent to pointer1 = array2
Now pointer1 and pointer2 are pointing to the same array, array2.
In C# you can overload the = to copy the arrays. In C it is just simple assignment.
In C arrays decays to pointers for the sake of simplicity. In C *(array + N) == array[N] and *array == array[0]
int array1 [5]; it is not the array of pointers only integers so *array1 = &array2; assigns array[0] with address of the first element of the the array2 converted to signed integer which generally doesn't make too much sense and it does not copy array2 to array
To copy array you need to use memcpy or the loop to copy the element. You need to make sure that the destination array is large enough to accommodate the second array. C will not change the destination array size.
The assignments that your are doing is wrong. Basically a pointer points to a block of memory. from your code I can understand that array1 = array2; and *array1 = &array2; is wrong.
Syntax in C is something like this data-type* pointer-variable = (data-type*)malloc(no. of bytes you want);
See consider you want 10 block of memory of type int
int *p = (int *)malloc(10 * sizeof(int))
sizeof(int) return 4 bytes.
Now p points to 10 * 4 = 40 bytes of memory, I multiplied by 4 because int is usually of 4 bytes and double is of 8 bytes and so on.
Follow this link to understand C - Data Types
Now regarding changing pointers refer below example and read the comments
int *q = NULL // declare a pointer of same type as the block of memory it is going to point
q = p; //now q and p point same memory of 40 bytes, means value at q[0] is equal to p[0]
When you have an integer pointer and you increment it by p++ it will point to next memory location p[1], pointer will be exactly incremented by 4 bytes as int size is 4 bytes and for double it will be 8 bytes, for char it will be 1 byte and so on.
Now if you want to increase the size of dynamically allocated memory you can use realloc please follow this link to understand more.
Dynamic Memory Allocation in C
int *p = NULL;
// Dynamically allocate memory using malloc()
p = (int*)malloc(no. of bytes, sizeof(int));
// Dynamically re-allocate memory using realloc()
p = realloc(p, (no. of bytes) * sizeof(int));
// Avoid memory leaks
free(p);
Syntax in C++ is something like this data-type* pointer-variable = new data-type[size];
See consider you want 10 block of memory of type int
int *p = new int[10]
Just use new operator to allocate block of memory and use delete to free allocated memory to avoid memory leaks.follow this link
new and delete operators in C++ for dynamic memory
Or If you are looking for containers where you don't know how much memory should be allocated the use standard template library vector, it helps creating dynamic arrays.follow this link
Vector in C++ STL

char pointers (strings) compared vs other pointers in C

When we create a pointer to int we need to point that pointer to a variable, but when we create a string we only need to point to a word (exemple).
I can't understand why strings can point to values (chars) and other pointers of type int, float can't.
A pointer of to int can point to a value that isn't contained in a variable:
int* p;
p = malloc(sizeof(int));
*p = 5;
The value 5 isn't contained in any variable, but p is pointing to it.
Your question really concerns how pointers are initialized. There is an element of arbitrariness in the way that string literals can initialize a char pointer and array literals can initialize arrays but int literals can't initialize int pointers. Ultimately, that is just the way the language is. With the way that int pointers are typically used (to either pass variables by reference or in dynamic data structures), there really isn't very many natural use-cases for initializing a single int pointer to point to a literal value when declaring it.
char* c = {'H','i','\0'};
is the same as:
char* c = "Hi";
sort of like:
int* a = {0,1,2,3};
is the same as:
int* a = malloc(sizeof(int) * 4);
a[0] = 1;
a[1] = 2;
...
...
A pointer is a reference to a memory location of the type the pointer was declared to point at, in this case a char.
An array of say 10 chars char* c[10]; is 10 continuous memory locations (each the size of 1 char). Here c points to the first location in that continuous memory array. You can randomly access the 10 memory locations using the [] operator. c[0] = 'H'; c[1] = 'i'; or using pointer arithmetic *c = 'H'; c++; *c = 'i';
This may help: http://www.cplusplus.com/doc/tutorial/ntcs/
In C a string literal is not a scalar value but an array of char

C: append char* to char**

I'm really new to C pointers and I'm coming from Java/C++. I am trying to append a char* c to a char** cArray. Here is kind of what I have so far:
char **cArray = "abc";
char *c = "def";
cArray += &c;
printf("%s", cArray)
and output should be: abcdef
My question is, How do I append a char * to a char ** in C?
Thank you for any tips you have!
You seem to have a misunderstanding of what a pointer and an array are. First lets start with an array. An array is a contiguous fixed-size block of memory. That is to say, an array is a constant number of values next to each other.
So, to start with, the idea of "Appending" an array makes sense in the way that you can add an item to the next empty spot in an array. But it would not be right to say the array is growing. An array is not the equivalent of Java's Array List.
Lastly, I will point out static arrays are declared with:
int val[3];
Where 3 can be any other constant value interpreted as a size_t.
Next, lets discuss pointers. Pointers are not arrays, do not confuse the two- although many people find it comforting to think of them as interchangeable (and for the most part you can get away with it!). However, this is one of the cases where they are not. So what are pointers?
Pointers denote the location of a value in memory. So, a pointer could say point to an element in our val array we created above. If we created a pointer to point at each element in our val array and we printed them all to stdout we would see that they are all 4 bytes away from each other. This is because arrays have their values located right next to each other (contiguous in memory) and sizeof(int) would return 4 (on my system).
Your main misunderstanding seems to be that pointers need to point to anything at all. They do not. Just like you can have a value which holds no information (or all of the bits are set to 0), you can surely have a pointer that points no nowhere at all. As a matter of fact that's exactly what you do.
char **cArray = "abc";
char *c = "def";
cArray += &c;
printf("%s", cArray);
Okay, lets take this apart line by line. First you declare a char ** called cArray and initialize it to "abc". Well, your variable cArray is a pointer to a pointer. The value "abc" I believe is a const char*. Therefore, you probably don't want to assign a pointer to a character as a pointer to a pointer. The consequence being, the value "abc\0" will be interpreted as another memory address. This, obviously, will not point to anything useful and accessing this memory would result in a seg fault.
Next, you initialize c to be a cstring containing "def".
Finally, you increment the address pointed to by cArray by whatever address "def" happens to be located at. So now, cArray is no longer even pointing to "abc" at all (nevermind interpreting it incorrectly).
Then we try to print some block of memory pointed to by cArray that is in no way even remotely close to any of the bits our program wants to be touching.
All of this said, say I had two cstrings and I wanted to get a third such that it is the first appended to the second:
char* a = "abc";
char* b = "def";
size_t sizeA = strlen(a);
size_t sizeB = strlen(b);
size_t size = sizeof(char) * (sizeA + sizeB + 1); //Size of our new memory block large enough to contain both a and b.
//Leave additional space for null terminator
char* c = malloc(size); //Actually allocate new memory
memcpy(c, a, sizeA); //Copy a into the first half of c
memcpy(c + sizeA, b, sizeB); //Copy b into the second half
c[sizeA + sizeB] = '\0'; //Assign null terminator to last character
printf("%s", c);
free(c); //Never forget

Resources