C -> sizeof string is always 8 - c

#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!

Related

Check if two arrays have been concatenated correctly in C

The following function allows me to calculate the length of a character string:
int arrayLen (char array[])
{
int i = 0;
while ( array[i] )
++i;
return i;
}
The problem is, if an array has 20 elements but only uses, say, 5 of them (including the null character \0), then the function will return 5. So from this, it's difficult to know how many characters the string can support in a function. Unfortunately, sizeof can't be used since the array is dynamically-allocated.
Here is an example of the basic function I'm trying to create, it allows the user to insert a character string into another character string at the index of the source[]:
void insertString (char source[], char insert[], int index)
{
int n = arrayLen (insert);
char temp[n];
// Replace characters from index with characters in insert array
for ( i = 0; source[index + i] && insert[i]; ++i )
{
temp[i] = source[index + i];
source[index + i] = insert[i];
}
// Concatenate replaced characters onto source array
for ( i = 0; temp[i]; ++i )
source[index + n + i] = temp[i];
}
The above code works fine until source[] isn't big enough to contain itself and the elements insert[]. Is there anyway to test for this and inform the user?
Update
I understand the limitations of finding the length of an array but is there a way to check if the array has been concatenated correctly onto the source[]?
e.g.
input = the wrong son
output = the wrong person▒▒"
In C, you need to explicitly tell the compiler the buffer size as a parameter since all the elements in an array are not copied into the array parameter; instead they are referenced by a pointer. - T.C.
Additional Info:
sizeof array / sizeof array[0] doesn't work since sizeof array references the size of the pointer to the first element in array, not the size of all the elements in the array. This would only work if the array was declared in the same function was the sizeof calculations.
You could, however, calculate how many elements are occupied in the array as follows:
int i = 0;
while ( array[i] )
++i;
This works if the array is ended by a null character \0. If the array has more space reserved than whats actually used, the above function will fail to identify that.
If you're not passing the actual buffer size to the function, there is no way to determine its size. When you pass an array to a function, it decays to a pointer:
unsigned wrong_sizeof(char arr[])
{
return (unsigned)sizeof arr;
}
int main(void)
{
char s[] = "Hello world!";
char *p;
printf("wrong_sizeof(s): %u\n", wrong_sizeof(s));
printf("sizeof p: %u\n", (unsigned) sizeof p);
printf("sizeof s: %u\n", (unsigned)sizeof s);
return 0;
}
That program first prints the incorrect size calculation, which is incorrect because the function wrong_sizeof receives a pointer to the first element of the array (&s[0]) instead the entire array itself. This is something the C language specification requires.
Next is the size of a pointer using the sizeof operator directly, followed by the size of the array using the sizeof operator directly instead of the function. This proves that the function receives a pointer.
To conclude, you must pass one of two things:
the size of the output buffer
the number of characters to copy
With either one of these, it is no longer your fault as the designer of the function if an incorrect parameter is passed because you're only doing what you're told, similar to strncpy, strcat, etc.
Edit
To address the update:
new_size == source_length - i + insert_size
The size required by the new string, including the null terminator, is the number of characters in the source string, excluding the null terminator, plus the number of characters required for storing the string to insert, including the null terminator. For example:
char buf[] = "Hello, world!"
insertString(buf, "John", 7);
printf("%s\n", buf);
will result in a new string requiring 14 - 7 + 5, or 12, characters: 7 for "Hello, " and 5 for "John\0".

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

How to create a string of variable length with character X in C

I am new to C and am having some troubles with strings. How do I create a string of variable length containing a specified character in C? This is what I have tried but I get a compiler error:
int cLen = 8 /* Specified Length */
char chr = 'a'; /* Specified Character */
char outStr[cLen];
int tmp = 0;
while (tmp < cLen-1)
outStr[tmp++] = chr;
outStr[cLen-1] = '\0';
/* outStr = "aaaaaaaa" */
You can try:
char *str = malloc(cLen + 1);
memset(str, 'a', cLen);
str[cLen] = 0;
Strings in C might not be as flexible as you want, on the first look.
What you did with "char outStr[]" was to indicate you'd like a pointer to char, that can be iterated with array syntax... it creates no actual storage for the characters, because you never mentioned how many you would like to store.
In C you can have the storage decoupled from these special variables, called pointers. The example of wanting a variable length string is actually a good example of why would you want that: I want an entity that holds knowledge of where the storage is at; I want methods to allow me to change the storage size.
So, you prepare yourself to deal with dynamic memory allocation by including
#include <stdlib.h>
declare a pointer to chars by
char *cpString;
you ask for an allocation of "n" chars with
cpString=malloc(n*sizeof(char));
Now you can strcat, printf, whatever you want to do with a string that has n-1 charaters (because it must be null terminated).
Specifically, you can now initialize your string with
memset(cpString,X,n-1);
cpString[n]=0;
which creates a XXXX...XXX\0 string, of n-1 characters.
When you want to change cpString storage size, here's the tricky part, you need to free the allocated memory before you request for a new storage allocation
if (cpString !=0)
{
free(cpString);
cpString=0;
}
cpString=malloc(n*sizeof(char));
otherwise the dynamic memory storage area (called a "heap") is left with an un-reclaimable piece of the old n size.
There are better allocators, that don't need free(), but I better leave you studying and practicing with malloc() free() usage.
There's no need to use strncat(), strings are just character arrays so do the assignment directly character by character:
void repeated_string(char *out, size_t len, char v)
{
for(; len > 0; --len)
*out++ = v;
*out = '\0';
}
There are two issues with your code:
1) the length is (probably) not what you're expecting. You have:
int cLen = 8; /* Specified Length */
Presumably you want a string of length 8. Because you have to add a NULL terminator, you're only getting a string of length 7 right now. If that's what you want you should just update your comment to make that clear:
int cLen = 9; /* Specified Length (8) + 1 for NULL */
2) you're not assigning the char correctly:
char chr = "a";
is not right. Characters are specified with a single quote:
char chr = 'a';
After that your code should work.

Create a string array with Characters in C

When I do this
char *paths[10];
paths[0] = "123456";
printf(1,"%s\n",paths[0]);
printf(1,"%c\n",paths[0][2]);
Output:
123456
3
But when I you do this
char *paths[10];
paths[0][0]='1';
paths[0][1]='2';
paths[0][2]='3';
paths[0][3]='4';
paths[0][4]='5';
paths[0][5]='6';
printf(1,"%s\n",paths[0]);
printf(1,"%c\n",paths[0][2]);
Output:
(null)
3
Why it is null in this case?
How to create a string array using characters in C? I am a bit new to C and feeling some difficulties to program in C
You have a lot of options provided by various answers, I'm just adding a few points.
You can create a string array as follows:
I. You can create an array of read only strings as follows:
char *string_array0[] = {"Hello", "World", "!" };
This will create array of 3 read-only strings. You cannot modify the characters of the string in this case i.e. string_array0[0][0]='R'; is illegal.
II. You can declare array of pointers & use them as you need.
char *string_array1[2]; /* Array of pointers */
string_array1[0] = "Hey there"; /* This creates a read-only string */
/* string_array1[0][0] = 'R';*/ /* This is illegal, don't do this */
string_array1[1] = malloc(3); /* Allocate memory for 2 character string + 1 NULL char*/
if(NULL == string_array1[1])
{
/* Handle memory allocation failure*/
}
string_array1[1][0] = 'H';
string_array1[1][1] = 'i';
string_array1[1][2] = '\0'; /* This is important. You can use 0 or NULL as well*/
...
/* Use string_array1*/
...
free(string_array1[1]); /* Don't forget to free memory after usage */
III. You can declare a two dimensional character array.
char string_array2[2][4]; /* 2 strings of atmost 3 characters can be stored */
string_array2[0][0] = 'O';
string_array2[0][1] = 'l';
string_array2[0][2] = 'a';
string_array2[0][3] = '\0';
string_array2[1][0] = 'H';
string_array2[1][1] = 'i';
string_array2[1][2] = '\0'; /* NUL terminated, thus string of length of 2 */
IV. You can use pointer to pointer.
char ** string_array3;
int i;
string_array3 = malloc(2*sizeof(char*)); /* 2 strings */
if(NULL == string_array3)
{
/* Memory allocation failure handling*/
}
for( i = 0; i < 2; i++ )
{
string_array3[i] = malloc(3); /* String can hold at most 2 characters */
if(NULL == string_array3[i])
{
/* Memory allocation failure handling*/
}
}
strcpy(string_array3[0], "Hi");
string_array3[1][0]='I';
string_array3[1][1]='T';
string_array3[1][2]='\0';
/*Use string_array3*/
for( i = 0; i < 2; i++ )
{
free(string_array3[i]);
}
free(string_array3);
Points to remember:
If you are creating read-only string, you cannot change the character
in the string.
If you are filling the character array, make sure you have
memory to accommodate NUL character & make sure you terminate your
string data with NUL character.
If you are using pointers &
allocating memory, make sure you check if memory allocation is done
correctly & free the memory after use.
Use string functions from
string.h for string manipulation.
Hope this helps!
P.S.: printf(1,"%s\n",paths[0]); looks shady
char *paths[10];
paths[0][0]='1';
paths is an array of pointers. paths is not initialized to anything. So, it has garbage values. You need to use allocate memory using malloc. You just got unlucky that this program actually worked silently. Think of what address location would paths[0][0] would yield to assign 1 to it.
On the other hand, this worked because -
char *paths[10];
paths[0] = "123456";
"123456" is a string literal residing in the reading only location. So, it returns the starting address of that location which paths[0] is holding. To declare correctly -
const char* paths[10];
paths is an array of 10 pointers to char. However, the initial elements are pointers which can not be dereferenced. These are either wild (for an array in a function) or NULL for a static array. A wild pointer is an uninitialized one.
I would guess yours is static, since paths[0] is NULL. However, it could be a coincidence.
When you dereference a NULL or uninitialized pointer, you're reading or writing to memory you don't own. This causes undefined behavior, which can include crashing your program.
You're actually lucky it doesn't crash. This is probably because the compiler sees you're writing a constant to paths[0][2], and changes your printf to print the constant directly. You can not rely on this.
If you want to have a pointer you're allowed to write to, do:
paths[0] = malloc(string_length + 1);
string_length is the number of characters you can write. The 1 gives you room for a NUL. When you're done, you have to free it.
For your second example, if you know the size of each string you can write e.g.
char paths[10][6];
paths[0][0]='1';
...
paths[0][5]='6';
This way you have 10 strings of length 6 (and use only the first string so far).
You can define the string yourself, right after
#inlcude <stdio.h>
like this
typedef char string[];
and in main you can do this
string paths = "123456";
printf("%s\n", paths);
return 0;
so your code would look like this
#include <stdio.h>
typedef char string[];
int main() {
string paths = "123456";
printf("%s", paths);
}

Initialize a string in C to empty string

I want to initialize string in C to empty string.
I tried:
string[0] = "";
but it wrote
"warning: assignment makes integer from pointer without a cast"
How should I do it then?
In addition to Will Dean's version, the following are common for whole buffer initialization:
char s[10] = {'\0'};
or
char s[10];
memset(s, '\0', sizeof(s));
or
char s[10];
strncpy(s, "", sizeof(s));
You want to set the first character of the string to zero, like this:
char myString[10];
myString[0] = '\0';
(Or myString[0] = 0;)
Or, actually, on initialisation, you can do:
char myString[10] = "";
But that's not a general way to set a string to zero length once it's been defined.
Assuming your array called 'string' already exists, try
string[0] = '\0';
\0 is the explicit NUL terminator, required to mark the end of string.
Assigning string literals to char array is allowed only during declaration:
char string[] = "";
This declares string as a char array of size 1 and initializes it with \0.
Try this too:
char str1[] = "";
char str2[5] = "";
printf("%d, %d\n", sizeof(str1), sizeof(str2)); //prints 1, 5
calloc allocates the requested memory and returns a pointer to it. It also sets allocated memory to zero.
In case you are planning to use your string as empty string all the time:
char *string = NULL;
string = (char*)calloc(1, sizeof(char));
In case you are planning to store some value in your string later:
char *string = NULL;
int numberOfChars = 50; // you can use as many as you need
string = (char*)calloc(numberOfChars + 1, sizeof(char));
To achieve this you can use:
strcpy(string, "");
string[0] = "";
"warning: assignment makes integer from pointer without a cast
Ok, let's dive into the expression ...
0 an int: represents the number of chars (assuming string is (or decayed into) a char*) to advance from the beginning of the object string
string[0]: the char object located at the beginning of the object string
"": string literal: an object of type char[1]
=: assignment operator: tries to assign a value of type char[1] to an object of type char. char[1] (decayed to char*) and char are not assignment compatible, but the compiler trusts you (the programmer) and goes ahead with the assignment anyway by casting the type char* (what char[1] decayed to) to an int --- and you get the warning as a bonus. You have a really nice compiler :-)
I think Amarghosh answered correctly. If you want to Initialize an empty string(without knowing the size) the best way is:
//this will create an empty string without no memory allocation.
char str[]="";// it is look like {0}
But if you want initialize a string with a fixed memory allocation you can do:
// this is better if you know your string size.
char str[5]=""; // it is look like {0, 0, 0, 0, 0}
It's a bit late but I think your issue may be that you've created a zero-length array, rather than an array of length 1.
A string is a series of characters followed by a string terminator ('\0'). An empty string ("") consists of no characters followed by a single string terminator character - i.e. one character in total.
So I would try the following:
string[1] = ""
Note that this behaviour is not the emulated by strlen, which does not count the terminator as part of the string length.

Resources