C basics: comparing "*char" and "char[x]" for string creation - c

A pretty basic C question. Why do the following two commands result in the creation of strings that have different sizes?
As you can see below, method 1 creates a string with size 8 bytes and method 2 creates a string with size 5 bytes.
Am confused as to why method 1 is creating a string of size 8 bytes...
(I've already seen these posts: Difference of sizeof between char* x and char x[] and What is the difference between char s[] and char *s?. Unless I had a reading-comprehension-fail, it doesn't really address why method 1 creates a string of size 8 bytes... According to the responses, it would seem that method 1 should be creating a pointer of size 4 bytes.)
Method 1:
char *string = "ABCD";
Method 2:
char string2[5] = "ABCD";
For example, when I run the following program, I get the output shown below.
#include <stdio.h>
int main(int argc, char *argv[])
{
char *string = "ABCD";
printf("Based on \"char *string = \"ABCD\":\n");
printf("Size of string: %ld\n",sizeof(string));
printf("Size of each element of string: %ld\n",sizeof(string[0]));
printf("String: %s\n\n", string);
char string2[5] = "ABCD\0";
printf("Based on \"char string2[5] = \"ABCD\":\n");
printf("Size of string: %ld\n",sizeof(string2));
printf("Size of each element of string: %ld\n",sizeof(string2[0]));
printf("String: %s\n\n", string2);
return 0;
}
Output of the above program:

that's because in this line char *string = "ABCD"; you are declaring a pointer to char which a size of 8 bytes where as in this line char string2[5] = "ABCD"; you are declaring an array of 5 chars and since a char is 1 byte long and 1 * 5 == 5 bytes then the size of string2 will be 5 bytes

A char only has to hold an ASCII value, which is a very small range of numbers, so they only take up 1 byte each.
A char* is a pointer to an address in memory, which is a much larger range of numbers, hence more bytes are required to store it. A pointer on a 32-bit system takes up 4 bytes, and on a 64-bit system, takes up 8 bytes.
I take it you're running on a 64-bit system? I think that's why it's 8 bytes.

In your first example you declare a variable that is a pointer to a char. So, when you take its size with sizeof, you get the size of the pointer (not the size of the thing it's pointing at), which is 8 bytes on a 64-bit platform.
In the second example, you declare a variable that is an array of char. In C, the sizeof an array does as you would expect - it returns the size of the array in bytes, which in this case is 5 * sizeof(char) (since you declared a 5 character array), which is 5 (since sizeof(char) = 1).
In either case, using sizeof is generally not the correct way to measure the length of a string - you should be using strlen instead. This will correctly handle cases where the string terminator character NUL appears somewhere other than at the end of the char array.

Related

Generic type swap c function

I am trying to write a simple function that will swap any two variables of the same of type.
void swap(void* a, void* b, int size);
void swap(void* a, void* b, int size){
void* temp = malloc(size);
memcpy(temp, a,size);
memcpy(a, b, size);
memcpy(b, temp,size);
free(temp);
}
int main(int argc, char* argv[])
{
char name[] = "name";
char greet[] = "greet";
swap(name, greet, 30);
printf("%s\n", name);
printf("%s\n", greet);
return 0;
}
But what the above code prints is:
`
name
The value of pointed to by a (in swap) changes to ` after memcpy(b, temp, size), I am unsure why?
When you call memcpy(b, temp,size); with size being equal to 30 and the actual size of the string pointed by b being 6, you basically write past the memory you own.
In your case, your program will actually damage the program stack. If in memory b comes before a the additional 24 will effectively rewrite the contents of a completely.
You have to check whether the size is less than or equals the least size of the both strings + 1 (to account for the null character).
There are some bugs, resulting in undefined behavior.
1. You are copying 30 bytes from an array, which is 5 bytes long ("name" is 4 chars + 1 byte of trailing 0).
2. You are copying 30 bytes to array, which is 6 bytes long ("greet" is 5 chars + 1 byte of trailing 0).
Both bugs can cause the problem, especially the second one: you are trying to use 24 bytes of memory over array bounds - it is not possible to determine the results of this.
As someone wrote in comments, the better way will be exchanging the pointers, nor pointed bytes.
As noted by the comments, you cannot swap greet and name, as their types do not match: char[6], vs char[5] (including terminating NUL), and they have different size.
However, the swap can be used on char * object, since char array can be converted to char *, the change is simple.
int main(int argc, char* argv[])
char name[] = "name";
char greet[] = "greet";
char *p1 = name ;
char *p2 = greet ;
swap(&p1, &p2, sizeof(p1)) ;
printf("%s\n", p1);
printf("%s\n", p2);
}
Side note: No need to use malloc for the temp space, unless you are expecting to move very large objects. Just char temp[size] ; will do the work - instead of malloc - and no need to free (and minor performance gain).

Why is char *str = "anything" always the size of 8?

I was testing around with sprintf a bit to convert an int into a string/char and noticed something:
When I make a string like this
char *str = "anything";
no matter what I write in it, sizeof always returns a value of 8 byte.
But as far as I know, a char is ususally the size of 1 byte, so why doesn't the number of characters in the string/array change its size?
If I write
char str[15];
I get a size of 15 bytes, so why do I not get a size of 15 bytes if I type
char *str = "11111111111111\0"
but a size of 8 bytes?
Similar to this, if I type
char str[] = {"67"}
sizeof returns a value of 3 byte, which makes sense since it is 6, 7 and \0.
And then I write this
int aInt = 368;
sprintf(str, "%d", aInt);
to convert int aInt 368 into a string and write that string into str.
These are three char then, and therefor, sizeof should return a value of 4 byte, counting \0 in.
But it still returns 1, even through I wrote 3 chars.
Can anyone explain this to me, please?
This is the piece of code with which I've been testing this:
#include <stdio.h>
int main(int argc, char *arfv[])
{
int aInt = 368;
printf("value of aInt: %d\n", aInt);
char str[15];
//Other ways of creating a string/array which were tested:
//char *str = "anything";
//char str[] = {"67"};
//printf("value of str before: %s\n", str); //value of str before converting
printf("size of str before: %ld\n", sizeof(str)); //size of str before converting
sprintf(str, "%d", aInt); //convert aInt into a string
printf("value of str after: %s\n", str); //value of str after converting
printf("size of str after: %ld\n", sizeof(str)); //size of str after converting
return 0;
}
A char* is just a pointer to some memory, and has a size of whatever a pointer is on your architecture (8 bytes would indicate a 64-bit architecture, 4 bytes would indicate 32-bit).
Since pointers convey no information about the size of the allocation they point to, sizeof will not evaluate to the size of the allocation, it will simply tell you how large the pointer is. Further, note that sizeof is a compile time construct; its value is evaluated fully at compile time.
char *ptr = "1234567890";
char str[10] = "12345";
int numbers[10];
sizeof(ptr) evaluates the size of the pointer. The value will typically be 4 (32-bit) or 8 (64-bit).
sizeof(*ptr) evaluates the size of char. (1)
sizeof(str) evaluates the size of the array. (Its size is 10 bytes, even though only 6 were assigned.)
sizeof(numbers) will evaluate to sizeof(int) * 10.
sizeof gives you the number of bytes necessary to store a value of a given type. For a char * this is usually 4 or 8 bytes. A char * can store a memory address were you may find chars. How many chars are at such an address ? If these chars encode a C-string, then you can use strlen to get the length of the string.

parsing a string using pointer pointing to a string without using strdup and strtok functions

I am writing a code in which i want to parse a incoming string(basically this is for embeddded project, but i want to test it first in C).The string can be a GPS output , basically a NMEA string.Even though i had done parsing using strdup and strtok function but i am, stucked up when i am doing parsing simply using a string and pointer pointing to that string.
#include<stdio.h>
int main()
{int i;
char inputstring[100]; //i assumed it to be input string, in this case enter by user.
char *ptr[12];
printf("Enter the string to be printed now.: \n");
scanf("%s",inputstring);
printf("the input string being received from the user is = \n %s \n", inputstring);
for(i=0;i<12;i++) /*used this for loop to get first 12 characters from inputstring copied into ptr[i] */
{
ptr[i] = &inputstring[i];
}
printf("value of store is = %s \n",*ptr);
return 0;
}
but the ouput of this is whole inputstring rather then the first 12 characters.I dig this out further and find that *ptr when points to inputstring, its points to the inputstring[0]
and will copy whole string in it rather then just copying first 12 characters.How can we limit this ?
Need help.I have a alternate way but need help to dig out this code of mine.
This:
char *ptr[12];
is an array of 12 character pointers, but you seem to want it to be an array of 12 characters. Remove the asterisk:
char ptr[12];
and re-name it, since ptr is a lousy name:
char tmp[12];
Then make sure that you terminate it, and have room for the terminator:
char tmp[13];
strlcpy(tmp, inputstring, sizeof tmp);
char ptr[12];
instead of
char *ptr[12];
char ptr[12]: is an array of characters with size = 12 elements of chars. the size of each element in the array is = the size of char (1 byte).
char *ptr[12]: is an array of pointers with size = 12 elements of pointers. the size of each element in the array is = the size of pointer (4 bytes for 32-bit systems and 8 bytes for 64-bit systems). each pointer in the array could point to a string (char array).
you should use the following code instead
for(i=0;i<12;i++)
{
ptr[i] = inputstring[i];
}
or more simple
memcpy(ptr, inputstring, 12);
and you have to add null charachter at the end of your ptr string before you print the ptr string.
So you have to add 1 element to the size of the ptr char array
char ptr[13];
memcpy(ptr, inputstring, 12);
ptr[12] = '\0';
printf("value of store is = %s \n",ptr);

why is this not the same: char dog[1000]; and char *dog = (char*)malloc(1000 * sizeof(char));

when I "print" the sizeof(dog) for
char dog[1000];// i get size of 1000
char *dog = (char*)malloc(1000 * sizeof(char));// i get size of 8 ? why?
thx
The first variable has type char[1000] which is an array of 1000 chars.
The second variable has type char * which is a pointer. On your system it appears that pointers have a size of 8 (probably because you have 64-bit pointers).
Because char *dog is just a single pointer whereas char dog[1000] an array of chars.
The important point to note is that sizeof dog[1000] is determined is known at compile time whereas dynamic array (char *dog) is unknown.

C -> sizeof string is always 8

#include "usefunc.h" //don't worry about this -> lib I wrote
int main()
{
int i;
string given[4000], longest = "a"; //declared new typdef. equivalent to 2D char array
given[0] = "a";
printf("Please enter words separated by RETs...\n");
for (i = 1; i < 4000 && !StringEqual(given[i-1], "end"); i++)
{
given[i] = GetLine();
/*
if (sizeof(given[i]) > sizeof(longest))
{
longest = given[i];
}
*/
printf("%lu\n", sizeof(given[i])); //this ALWAYS RETURNS EIGHT!!!
}
printf("%s", longest);
}
Why does it always return 8???
There is no string data type in C. Is this C++? Or is string a typedef?
Assuming string is a typedef for char *, what you probably want is strlen, not sizeof. The 8 that you are getting with sizeof is actually the size of the pointer (to the first character in the string).
It is treating it as a pointer, the sizeof a pointer is obviously 8bytes = 64 bits on your machine
You say "don't worry about this -> lib i wrote" but this is the critical piece of information, as it defines string. Presumably string is char* and the size of that on your machine is 8. Thus, sizeof(given[i]) is 8 because given [i] is a string. Perhaps you want strlen rather than sizeof.
This is common mistake between the array of characters itself, and the pointer to where that array starts.
For instance the C-style string literal:
char hello[14] = "Hello, World!";
Is 14 bytes (13 for the message, and 1 for the null terminating character).
You can use sizeof() to determine the size of a raw C-style string.
However, if we create a pointer to that string:
char* strptr = hello;
And attempt to find it's size with sizeof(), it will only always return the size of a data pointer on your system.
So, in other words, when you try to get the size of the string from a string library, you're truly only getting the size of the pointer to the start of that string. What you need to use is the strlen() function, which returns the size of the string in characters:
sizeof(strptr); //usually 4 or 8 bytes
strlen(strptr); //going to be 14 bytes
Hope this clears things up!

Resources