c lang - different array length by pointer - c

I have problem with my own function for get array length.
Code:
#include <stdio.h>
int main() {
int a[] = {5,4,1,2,1}; //len -> 6!! FAIL! WHY?
//int a[] = {5,4,1,2}; //len -> 4 OK!
int len = 0;
int *p = a;
while(*p != '\0'){
printf("%d\n", *p);
len++;
*p++;
}
printf("len: %d\n", len);
return 0;
}
code above output:
5
4
1
2
1
32767
len: 6
but this array int a[] = {5,4,1,2}; - produce len = 4 - ok.
why it happens?

It fails because there's no 0 at the end of your array. It's not added automatically, you need to do it explicitly. As a result, you accessed outside the array, which results in undefined behavior. The fact that one of your tests seemed to work was purely luck, you can't depend on it.
int a[] = {5, 4, 1, 2, 1, 0};
The only time that C automatically adds a null terminator is when you use a string literal to initialize a char array, e.g.
char c[] = "abcde";

Related

Why is the first element of the int array different from the one appended in for loop?

I have 2 questions.
First question is that, I'm trying to find the frequency of the sentence and put them into another array. However, the output of the new frequency nfreq is different from what is appended in for loop.
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int main()
{
char str[] = "test sentence";
char nstr[] = "";
int freq[256] = {};
int nfreq[256] = {};
for(int i = 0; str[i] != '\0'; i++)
{
freq[str[i]]++;
}
printf("\nCharacter Frequency\n");
int j = 0;
for(int i = 0; i < sizeof(freq) / sizeof(int); i++)
{
if(freq[i] != 0)
{
printf("%5c%10d\n", i, freq[i]);
char c = i;
append(nstr, c);
int f = freq[i];
nfreq[j] = f;
printf("Num in nfreq[%d] is %d\n", j, nfreq[j]);
j++;
}
}
for(int i = 0; i < strlen(nstr); i++)
{
printf("%d ", nfreq[i]);
}
printf("\n");
printf("size of nfreq : %lu\n", sizeof(nfreq) / sizeof(nfreq[0]));
printf("size of str : %lu\n", strlen(str));
printf("size of nstr : %lu\n", strlen(nstr));
printf("nstr is : %s\n", nstr);
return 0;
}
The frequency of each letter is
Character Frequency
1
c 1
e 4
n 2
s 2
t 3
and nfreq should have those {1, 1, 4, 2, 2, 3} in its array with the code above and it even
says Num in nfreq[0] is 1 and etc in the loop, but when I try to check what's in nfreq outside the loop, it outputs {116, 1, 4, 2, 2, 3} this instead. What is this 116 and it should be 1 for the frequency of ' '.
Also the second question is that, if I were not to declare the size of an int array, int nfreq[] = {} like so in the beginning, does the size of this array, after appending int with for loop, changes dynamically? Or does it stay 0?
I tried fixing it by not declaring the size (which I don't think it matters) of nfreq array.
Thanks in advance for your help :)
Edit :
Sorry I forgot to add append function.
char nstr[] = "";
nstr is an array of one character.
append(nstr, c);
...
s[len+1] = '\0';
len is 0, so len + 1 is 1. This line is writing out-of-bounds to nstr. nstr is char [1]. You can only nstr[0] = something. nstr[1] is invalid.
Do:
char nstr[256] = "";
if I were not to declare the size of an int array, int nfreq[] = {} like so in the beginning, does the size of this array, after appending int with for loop, changes dynamically?
Notes: the {} is technically invalid, use {0} Is an empty initializer list valid C code? . int nfreq[] = {} is technically invalid code, it doesn't make sense, if it would, then nfreq would have zero size.
There are no "dynamic" changes of array size. Array has constant size. Writing out-of-bounds to an array is an error in the code.
Invalid initialization:
int freq[256] = {};
is invalid. ISO C forbids empty initializer braces. An initializer-list must contain at least one initializer.
Perhaps:
int freq[256] = { 0 };
Re:
if I were not to declare the size of an int array, int nfreq[] = {}
like so in the beginning, does the size of this array, after appending
int with for loop, changes dynamically? Or does it stay 0?
Answer: No.
int nfreq[] = {};
is not a valid statement. The space doesn't change dynamically.
Either declare an automatic array with fixed size like this:
int nfreq[SIZE] = { 0 };
or dynamically allocate memory with malloc(), and reallocate with realloc() as necessary.
Incorrect format specifier:
strlen() and sizeof() returns a type size_t. %lu might not be the correct format specifier for size_t. Use %zu instead.
See also:
Writing to out of bounds memory:
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
You didn't allocate any memory for the array that has decayed to a pointer in append(). So this writes to out of bounds memory, and exhibits undefined behaviour.

why do i not get the correct value for sum?

#include <stdio.h>
#include <stdlib.h>
int sumArray(int* p);
int main(){
int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, sum;
int* p = array;
sum = printf("The sum of the array is: %d", sumArray(p));
return 0;
}
int sumArray(int* p){
int sum = 0;
while(*p){
sum += *p;
p++;
}
return sum;
}
when i run this code i get a 6-digit value for sum, which looks more like an address. so what exactly am i doing wrong here?
while(*p) is a pretty idiomatic way of processing character strings in C because they have the useful property of being null-terminated. Once the null terminator (character with numeric value of 0) is reached, *p is 0 and the loop ends.
Your array does not have this property so while(*p) is true for the entire length of your array, then it goes out of bounds, which is undefined behavior.
Your options are:
Pass the size along with the array, and use int i = 0; while (i < LENGTH){} or more idiomatically for(int i = 0; i < LENGTH; i++)
Use a designated sentinel value to indicate the end of the array and use while (*p != SENTINEL)
Former option is the least hassle and doesn't require you to designate an arbitrary int as a magic number.

Length of an array

I need to find the length of an array, how would I do this without using the sizeof function.
eg if
Array 1 = [0 1 2 3 4 5 6]
the size of this array would be 7.
If you can't use sizeof (tell us why, please), you can use a loop and a sentinel (-1 or some number that can not be used in the array):
int arr[] = {0, 1, 2, 3, 4, 5, 6, -1};
int count = 0;
while (arr[count] != -1) count++;
Many high-level programming language save the length of an array once it is created.
/* e.g. Java */
int[] foo = new int[10];
assert(foo.length == 10);
But the length of an array is not saved in C! This is useful as you can decide how you want to save the length with respect to optimization. You basically have three possibilities to get/save the length:
mark the end of the array with a certain value (i.e. \0 is used for strings)
char foo[] = "bar";
/* foo has length 4(sic!) as '\0' is automatically added to the end*/
int i = 0;
while(foo[i] != '\0'){
printf("%c",foo[i]);
i++;
}
save the length of the array in a variable
int foo[] = {1,2,3,4};
int length = 4;
for(int i = 0; i < length;i++){
printf("%i, ",foo[i]);
}
use sizeof (warning: sizeof is (mostly) computed at compile time and its use is restricted. you can only use sizeof within the function where the array has been created. when you pass an array to a function you only pass the pointer to the first element. therefore you can loop through this array as you know what offset must be used(type of its elements), but you do not know how big it is unless you also passed the length or added a sentinel value)
/* ok */
int foo[] = {1,2,3,4};
for(int i = 0; i < sizeof(foo)/sizeof(int);i++){
printf("%i, ",foo[i]);
}
/* not ok */
void foo(int bar[]);
void foo(int bar[]){
for(int i = 0; i < sizeof(bar)/sizeof(int);i++){
printf("%i, ",bar[i]);
}
}
int main()
{
int arr[] = {1,2,3,4};
foo(arr);
return 0;
}

Transferring values from a char array to an integer array in C programming

I am having the following problem. I have created a char array which represents a series of characters and numbers - this was designed to model a string read or got from a text file. I wish to then search this string using the "search" function defined below, pulling out only the numbers before 'H' and assigning to a separately defined integer array. I find when I use gdb, this function works fine. However, only part of the array is ever returned - the first 8 elements to be exact. Would anyone please be able to explain why this is from looking at the code below?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void search(char buffer[], int size, int array[]);
int main (void)
{
char buffer[1000];
memset(buffer, 0, sizeof(buffer));
buffer[0] = 2;
buffer[1] = 'H';
buffer[2] = 3;
buffer[3] = 'H';
buffer[4] = 6;
buffer[5] = 'H';
buffer[6] = 4;
buffer[7] = 'H';
buffer[8] = 6;
buffer[9] = 'H';
buffer[10] = 7;
buffer[11] = 'H';
buffer[12] = 11;
buffer[13] = 'H';
buffer[14] = 12;
buffer[15] = 'H';
buffer[16] = 17;
buffer[17] = 'H';
int* array ;
array = malloc(sizeof(buffer) * sizeof(int));
search(buffer, sizeof(buffer), array);
for(int i = 0, n = sizeof(array); i < n; i++)
{
printf("array[%d] = %d\n", i, array[i]);
}
free(array);
}
void search(char buffer[], int size, int array[])
{
int position = 0;
for (int i = 0; i < size; i++)
{
if(buffer[i] == 'H')
{
*(array + position) = buffer[i-1];
position++;
}
}
}
The compiler outputs the following:
array[0] = 2
array[1] = 3
array[2] = 6
array[3] = 4
array[4] = 6
array[5] = 7
array[6] = 11
array[7] = 12
which as can be seen is missing the ninth position in the array - value 17. In fact, if I fgets into a buffer a much bigger set of numbers and 'H's, I am always returned an array of size 8. Why is this? Any help would be much appreciated.
The problem here is with
n = sizeof(array)
array being a pointer, sizeof(array) will give you the size of the pointer (as sizeof(array) here is essentially sizeof(int *), which seems to be 8 for your platform), not the cumulative size (or number of elements) in the array.
One possible way to get what you want will be the search() to return the count of element put into the array and use that return value in the for loop for printing the required elements from array.
Replace n = sizeof(array) with n = strlen(buffer) / 2 will do (you want n to be the number of filled elements in the array).
Btw,
You need to make sure the buffer always has correct pairs.
Would be safer to declare the buffer like this char buffer[1000] = "";
"I am always returned an array of size 8" - that's because sizeof(int) in 64b-machine is 8 bytes, which is what you got from sizeof(array) - as array here is pointer.

How do I print all array elements on the same line?

I had to delete all the code. What I' looking is how to sprintf all elements of an array in the same line.
The display has 2 lines, I need to print the array 10,24,32,40,51, .....first line
and 10,51 .....second line
sample
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *join(int n, const int array[n], const char *format, const char *sep){
if(!format)
format = "%d";
if(!sep)
sep = ", ";
size_t len = strlen(sep)*(n-1)+1;//+1 for EOS
int i;
for(i=0;i<n;++i)
len += snprintf(NULL, 0, format, array[i]);
char *result = malloc(len);
if(!result)return NULL;
size_t pos = 0;
for(i=0;i<n;++i){
pos += sprintf(result + pos, format, array[i]);
if(i != n-1)
pos += sprintf(result + pos, "%s", sep);
}
return result;
}
int main (void){
int array[][5]={{10,24,32,40,51},{10,1,99,77,88}};
int row_size = sizeof(array)/sizeof(array[0]);
int col_size = sizeof(array[0])/sizeof(int);
char *join_str;
int i;
for(i=0;i<row_size;++i){
char *join_str = join(col_size, array[i], "%2d", ", ");
printf("%s\n", join_str);
free(join_str);
}
return 0;
}
Your array has 10 elements
#define N 10
int V[N] = {10,34, 34, 11};
However, it is partially explicitly initialised so that indices 0, 1, 2 and 3 contain 10, 34, 34 and 11 respectively. A partially explicitly initialised array in C will have the remaining elements (4 .. 9 inclusive) implicitly initialised to 0.
You then:
sprintf (str, "%d %d ... %d %d", V[0], V[1], V[N-2], V[N-1];
This isn't code you are actually running, as it is missing a ), and str is undefined. However, what this would do is write four values to str (not the screen), being values 0, 1, 8 and 9 (i.e. the first 2 and last 2 values), i.e. the characters 0 1 0 0 plus a terminating NULL.
As you are using sprintf() not snprintf() you have no way of checking whether this will overflow str.
It's difficult to tell what you are then doing because of the formatting of the question, but it appears you are calling a function array that might or might not modify the array and print it out again. However, your assembler function is defined as:
__asm void array (int V[], int N, int V) ....
which has an array / pointer parameter called V, a second parameter called N (though the main program #defines this to 10 (so that won't work), and a third parameter also called V which won't work as that's the name of the first parameter.
You also have a mysterious X defined to 10, which is then unused.
It's not particularly clear what you are asking and it would be better if you posted a small working code snippet, but I hope the above is of help.

Resources