C programming confused with output [duplicate] - c

This question already has answers here:
Weird behavior when printing array in C?
(5 answers)
Closed 9 years ago.
Can anyone please explain the output for the following program? I get an infinite loop if used a[i] = 0; and a segfault when I used a[i] = i; and also the i ranges between 0 - 9 when used a[i] = 0; whereas it goes to 39 when used a[i] = i; before giving a segfault.
#include<stdio.h>
#include<stdlib.h>
int mult(int a, int b);
int main()
{
int a[10];
int i = 0;
for(i=0; i < sizeof(a); i++)
{
a[i] = i;
printf("a[i]=%d i=%d\n", a[i], i);
}
return 0;
}

When you apply the sizeof operator to an array type, the result is the total number of bytes in the array, i.e, sizeof(a) determines the number of bytes in a which is not the number of elements in the array in this case. Use sizeof(a)/sizeof(a[0]) to get number of elements in the array a.
Replace
for(i=0;i<sizeof(a);i++)
with
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
Also, no need to initialize i twice.

You probably want to change this line:
for(i=0;i<sizeof(a);i++)
to this:
for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
Note:
sizeof(a) gives the number of bytes in a[].
sizeof(a)/sizeof(a[0]) gives the number of elements in a[].

sizeof doesn't do what you think it does. It's returning the number of bytes occupied by the entire array.
You want the numeric length of the array, not the byte size.
Try something like this:
const int array_size = 10;
int a[array_size];
for (int i = 0; i < array_size; i++) {
a[i] = i;
printf("a[%d] = %d\n", i, a[i])
}

If you want to know how far to loop, without storing it in a separate const, use sizeof(a)/sizeof(a[0])

Related

Why did the array lose the last element when passed into another function? [duplicate]

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
Closed 1 year ago.
I made an static int arr[3] and set to 1, 2, 3.
I can print 1, 2, 3 in the same function.
But when I pass the array it only prints 1, 2.
Why? What happened? How do I fix this?
#include <stdio.h>
void printArray(int* arr){
size_t n = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i<n; i++){
printf("%d\n",arr[i]);
}
}
int* makearray()
{
static int arr[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
printf("The Array before passing onto stack\n");
size_t n = sizeof(arr)/sizeof(arr[0]);
for(int i=0; i<n; i++){ printf("%d\n",arr[i]);}
printf("\nThe Array when attempting to pass to another function\n");
printArray(arr);
return arr;
}
int main(void) {
int* m = makearray();
return 0;
}
By converting your array to a pointer, you removed the information that sizeof needs to know its total length.
Instead, it just gives you the size of a single int *, which is twice the size of a single int on your machine.
Hence, you only see the first two elements.
In C, you're basically forced to pass around the length alongside the pointer. You can wrap the two in a struct to make it easier to use, but don't expect the niceties of other languages you may be used to.

How to give condition to my for loop to stop my integer pointer after reading all elements of my integer array?

#include<stdio.h>
#include<stdlib.h>
int main()
{ int a[3];
int *x=(int *) malloc (7*sizeof(int));
int *p=x;
scanf("%d %d %d",&a [0],&a[1],&a [2]);
for(int i=0;i<3; i++)
{
if(i==0)
for(int j=0; j<3;j++)
*p++=a[j];
else if (i==1)
for (int j=0; j<3; j++)
*p++=a[j]+a[(j+1)%3];
else
for(int j=0; j<3;j++)
*p+=a[j];
}
*(++p)= '\0';//id-001
int last=sizeof(x)/sizeof(x[0]);
printf("%d\n", last); //My expected output is 7 but why I'm getting 2?
p=x;
for(int i=0;p!='\0';i++){ //id-002
printf("%d ",x[i]);
p++;
}
}
How should I need to change id-001 to stop my integer pointer?
How should I need to change id-002 my for loop condition to stop after reading stored value in heap array?
int last=sizeof(x)/sizeof(x[0]);
This is incorrect since sizeof() only works for arrays who's size is known at compile time. In your case x is an allocated pointer so this is just dividing the size of a pointer (8 on x86_64) by the size of int (usually 4), hence you get 2.
I'm not sure what you exactly want to do with this program, but the termination condition here can be fixed:
for(int i=0;p!='\0';i++){
Here you're comparing the pointer with a NUL terminatior, not the value that the pointer points to. It should be changed to *p to check the value:
for(int i=0;*p!='\0';i++){
You don't need to advance the pointer again since it would've been advanced by the previous call to *p++ = something:
*(++p) = '\0'; // id-001
So change this to *p = '\0'.
There seems to be a typo in this loop, it should be changed to *p++ = a[j];:
for (int j = 0; j < 3; j++)
*p += a[j];
There is a buffer overflow in the loop itself since p is advanced without any bounds checks. It's advanced a total of 9 times which is out of bounds for size 7.

index out of bounds when accessing last item in array

I have a random number generator feeding numbers into an array, but when I print out the table, the last line is always a set of values out of the boundaries that I defined in the following function:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int temp[22];
int n;
for(n=0; n<23; n++){
temp[n] = rand()%(100 + 1 - 60) + 60;
printf("%d , %d \n", n, temp[n]);
}
return 0;
Ive created something of this nature before, but now its acting up, I just dont know where.
You are accessing the array outside the bounds which is undefined behaviour.
Instead make use of sizeof operator to avoid such problems:
for(n = 0; n < sizeof temp/sizeof temp[0]; n++)
But note that if temp were to be an malloc'ed pointer (int *temp = malloc(23 * sizeof *temp);) then sizeof wouldn't work.
Your array is being accessed outside of its bounds.
int temp[22];
This declaration assigns 22 indices to temp, temp[0] is the first
value and temp[21] is the last value you can access in your array. Counting 0, from 0..21 = we have 22 values
Your for loop is incorrect:
for(n=0; n<23; n++)
This will make the program attempt to access temp[22], which doesn't exist. You need to change it to:
for(n=0; n<22; n++)
Furthermore:
return 0; needs to be inside and at the end of your main() function. It's possibly a typo, but you're missing a closing brace } in your main() function, at least how you posted it.

Function passing of multidimensional array in c

#include <stdio.h>
void spiral(int a[10][10]) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int a[r][c];
for (i = 0; i < r; i++)
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
spiral(a);
return 0;
}
When I give a 3 x 6 array
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
The output is 14, while it should be 10
How to fix this issue?
If you enter 3 and 6 for r and c (respectively) then the type of a is not int[10][10] (or int(*)[10] as the spiral argument really is), it's int[3][6]. The memory layout is completely different for the arrays, leading to undefined behavior.
You can solve this by passing the size along to the function, and using it in the declaration of the array:
void spiral(const size_t r, const size_t c, int (*a)[c]) { ... }
Call it like expected:
spiral(r, c, a);
As noted using int a[r][c] as argument might be easier to read and understand, but it gives a false impression that a is actually an array. It's not. The compiler treats the argument as a pointer to an array of c integers, i.e. int (*a)[c].
This makes me a little conflicted... On the one hand I'm all for making things easier to read and understand (which means it will be easier to maintain), on the other hand newbies often get it wrong and think that one can pass an array intact when in fact it decays to a pointer which can lead to misunderstandings.
A few things are wrong: in void spiral() you ask for a 2D-array of 10*10, but you do not give that. Keep that part as a variable, so only ask the type you receive and not what you want to receive and with creating a dynamic array you should always do that with malloc or calloc and free them afterwards. This might be a bit hard at first, but when you start creating bigger programs this is a must if you have a question or do not understand the pointers in the program called (*) then ask me:
#include <stdio.h>
#include <stdlib.h>
void spiral(int **a) {
printf("%d", a[1][3]);
}
int main() {
int r, c, j, i;
scanf("%d%d", &r, &c);
int **a = malloc(r * sizeof(int*));
for (i = 0; i < r; i++) {
a[i] = malloc(c * sizeof(int));
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
scanf("%d", &a[i][j]);
}
}
spiral(a);
for (i = 0; i < r; i++) {
free(a[i]);
}
free(a);
return 0;
}

Integer Pointer Array

I have started an introductory class to C. I cannot explain the output that I get from running the code below
./a.out 6
Output is:
Array A elements: 0 1 2 3 4 5
Array B elements: 1 2 3 4 5 796830176
What I think the code is doing:
When manup_array is executed, each value of the respective pointers will be incremented, but since it is post-fix, this takes effect only later on after the original value is returned.
True enough, when we print array A first, we get 0 1 2 3 4 5 (i.e. before incrementation).
Subsequently when we print array B, the incrementation takes effect, so we get 1 2 3 [...]
What really puzzles me is why the last number is 796830176. Also, running this on various computers produces a different last number every time, suggesting that the pointer addressing is somehow responsible for this.
Could someone explain this to me?
Note:
The outputs of each array are identical (1 2 3 4 5 6) if I use the pre-fix operator. This is consistent with what I think is going on -> the pointers don't change; only the values get updated.
#include <stdio.h>
#include <stdlib.h>
void manup_array(int *array[], int n); // Forward declaration.
int main(int argc, char *argv[])
{
// The size N of 2 arrays are the same; obtain them from cmd line.
int N = atoi(argv[1]); // Convert from str to int in C.
int arrayA[N]; // Declare integer array.
int *arrayB[N]; // Declare integer pointer array.
for (int i = 0; i < N; i++)
{
arrayA[i] = i;
arrayB[i] = &arrayA[i]; // Assign address of each element in A to element in B.
}
manup_array(arrayB, N);
printf("Array A elements: ");
for (int i = 0; i < N; i++)
{
printf("%d ", arrayA[i]);
}
printf("\n");
printf("Array B elements: ");
for (int i = 0; i < N; i++)
{
printf("%d ", *arrayB[i]);
}
printf("\n");
return 0;
}
void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
*array[i]++;
}
}
This is really obscure code. What is does:
The function takes an array of pointers as parameter. Since the parameter to the function had type int *array[], any change of the items of array will affect the caller and alter arrayB.
The interesting part of the function is *array[i]++;. The operator precedence rules in C state that [] has higher prio than postfix ++, which has higher prio than unary *.
Since array is an array of pointers, array[i] gives you a pointer. Not a the value it points at. Then ++ increments the pointer to point at the next item in the arrayA of main.
And then finally there is a * which takes the contents of what that pointer pointed at, and then does nothing with them. The * is superfluous and just there to confuse the reader.
So back in main, you have changed all the pointers of arrayB. arrayB[0] now points at arrayA[1] and so on. The last item of arrayB will point one item past the end of arrayA, so for the last item, you access the array out-of-bounds and get a garbage value.
void manup_array(int *arr[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
int val = (*arr[0]); // get the value pointed to by the current value of arr
val++; // increment it
*(arr[0]) = val; // assign it back
arr++; // increase the pointer
}
}
Incredibly obtuse, but it demonstrates what you mean to do and how your obscure code muddled up the operators.
To add, makes debugging way easier!
manup_array() increments the pointer, not the value as expected.
Modified manup_array().
void manup_array(int *array[], int n) { // Take in B as input, then increase each elem by 1
for (int i = 0; i < n; i++)
{
//*array[i]++;
(*array[i])++;
}
}
I suggest to refer Pointer Arithmetic: ++*ptr or *ptr++?

Resources