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

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.

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

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

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.

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

Find the size of a string pointed by a pointer

#include <stdio.h>
int main ()
{
char *ptr = "stackoverflow"
}
Is there any way to find the length of stackoverflow pointed by ptr, as sizeof ptr always gives 4
Use strlen to find the length of (number of characters in) a string
const char *ptr = "stackoverflow";
size_t length = strlen(ptr);
Another minor point, note that ptr is a string literal (a pointer to const memory which cannot be modified). Its better practice to declare it as const to show this.
sizeof() returns the size required by the type. Since the type you pass to sizeof in this case is a pointer, it will return size of the pointer.
If you need the size of the data pointed by a pointer you will have to remember it by storing it explicitly.
sizeof() works at compile time. so, sizeof(ptr) will return 4 or 8 bytes typically. Instead use strlen.
The strlen() function provided by string.h gives you how many "real characters" the string pointed by the argument contains. However, this length does not include the terminating null character '\0'; you have to consider it if you need the length to allocate memory.
That 4 bytes is the size of a pointer to char on your platform.
#include<stdio.h>
main()
{
int mystrlen(char *);
char str[100];
char *p;
p=str;
printf("Enter the string..?\n");
scanf("%s",p);
int x=mystrlen(p);
printf("Length of string is=%d\n",x);
}
int mystrlen(char *p)
{
int c=0;
while(*p!='\0')
{
c++;
*p++;
}
return(c);
}
simple code to understand
You are looking for the strlen() function.
You can try using:
char *ptr = "stackoverflow"
size_t len = strlen(ptr);
if ptr length is an argument of a function it's reasonable to use pointers as a strings. we can get string length by following code:
char *ptr = "stackoverflow";
length=strlen((const char *)ptr);
And for more explanation, if string is an input string by user with variable length, we can use following code:
unsigned char *ptr;
ptr=(unsigned char *)calloc(50, sizeof(unsigned char));
scanf("%s",ptr );
length=strlen((const char *)ptr);
Purely using pointers you can use pointer arithmetic:
int strLen(char *s)
{
int *p = s;
while(*p !=’\0’)
{
p++; /* increase the address until the end */
}
Return p – s; /* Subtract the two addresses, end - start */
}
Even though this is a generic C question, it gets pretty high hits when looking this question up for C++. Not only was I in C/C++ territory, I also had to be mindful of Microsoft's Security Development Lifecycle (SDL) Banned Function Calls for a specific project which made strlen a no-go due to,
For critical applications, such as those accepting anonymous Internet connections, strlen must also be replaced...
Anyway, this answer is basically just a twist on the answers from the others but with approved Microsoft C++ alternative function calls and considerations for wide-character handling in respect to C99's updated limit of 65,535 bytes.
#include <iostream>
#include <Windows.h>
int wmain()
{
// 1 byte per char, 65535 byte limit per C99 updated standard
// https://stackoverflow.com/a/5351964/3543437
const size_t ASCII_ARRAY_SAFE_SIZE_LIMIT = 65535;
// Theoretical UTF-8 upper byte limit of 6; can typically use 16383 for 4 bytes per char instead:
// https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/
const size_t UNICODE_ARRAY_SAFE_SIZE_LIMIT = 10922;
char ascii_array[] = "ACSCII stuff like ABCD1234.";
wchar_t unicode_array[] = L"Unicode stuff like → ∞ ∑ Σὲ γνωρίζω τὴν ደሀ ᚦᚫᛏ.";
char * ascii_array_ptr = &ascii_array[0];
wchar_t * unicode_array_ptr = &unicode_array[0];
std::cout << "The string length of the char array is: " << strnlen_s(ascii_array_ptr, ASCII_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
std::wcout << L"The string length of the wchar_t array is: " << wcsnlen_s(unicode_array_ptr, UNICODE_ARRAY_SAFE_SIZE_LIMIT) << std::endl;
return 0;
}
Output:
The string length of the char array is: 27
The string length of the wchar_t array is: 47
strlen() gives you the exact length of the string [excluding '\0']
sizeof() gives you the size of the data type used.
// stackoverflow = 13 Characters
const char* ptr = "stackoverflow";
strlen(ptr); // 13 bytes - exact size (NOT includes '\0')
sizeof(ptr); // 4 bytes - Size of integer pointer used by the platform
sizeof(*ptr); // 1 byte - Size of char data type
strlen("stackoverflow"); // 13 bytes - exact size
sizeof("stackoverflow"); // 14 bytes - includes '\0'
#include<stdio.h>
int main() {
char *pt = "String of pointer";
int i = 0;
while (*pt != '\0') {
i++;
pt++;
}
printf("Length of String : %d", i);
return 0;
}
We can also use strlen() function or sizeof() operator which is builtin in C.
We can also take help of pointer arithmetic as above example.

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