Different places get different values [duplicate] - c

This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.

There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1

Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.

As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}

When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.

I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.

You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}

Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.

Related

Warning: Return from incompatible pointer type

The code below is producing a compiler warning: return from incompatible pointer type. The type I'm returning seems to be the issue but I cant seem to fix this warning.
I have tried changing the type of hands to int *. Also have tried returning &hands.
int * dealDeck(int numPlayers, int numCards, int cardDeck[])
{
static int hands[MAX_PLAYERS][MAX_CARDS]={0};
int start = 0;
int end = numCards;
int player, hand, j;
int card;
for(player = 0; player < numPlayers; player++)
{
for(hand = start, j=0; hand < end; hand++,j++)
{
card = cardDeck[hand];
hands[player][j] = card;
}
start = end;
end += numCards;
}
return hands;
}
This function should return a pointer to the array "hands". This array is then passed to another function which will print out its elements.
The hands variable is not an int * this is a int **
So you need to return a int **
This is a 2d array.
First of all, you have declared return type of int *, which would mean, that you are trying to return an array, while you want to return a 2-dimensional array. The proper type for this would usually be int **, but that won't cut it here. You opted to go with static, fixed size array. That means, that you need to return pointer to some structures of size MAX_CARDS * sizeof(int) (and proper type, which is the real problem here). AFAIK, there is no way to specify that return type in C*.
There are many alternatives though. You could keep the static approach, if you specify only up to 1 size (static int *hands[MAX_PLAYERS] or static int **hands), but then you need to dynamically allocate the inner arrays.
The sane way to do it is usually "call by reference", where you define the array normally before calling the function and you pass it as a parameter to the function. The function then directly modifies the outside variables. While it will help massively, with the maintainability of your code, I was surprised to find out, that it doesn't get rid of the warning. That means, that the best solution is probably to dynamically allocate the array, before calling the function and then pass it as an argument to the function, so it can access it. This also solves the question of whether the array needs to be initialized, and whether = {0} is well readable way to do it (for multidimensional array) , since you'll have to initialize it "manually".
Example:
#include <stdio.h>
#include <stdlib.h>
#define PLAYERS 10
#define DECKS 20
void foo(int **bar)
{
bar[0][0] = 777;
printf("%d", bar[0][0]);
/*
* no point in returning the array you were already given
* but for the purposes of curiosity you could change the type from
* void to int ** and "return bar;"
*/
}
int main()
{
int **arr;
arr = malloc(sizeof(int *) * PLAYERS);
for (size_t d = 0; d < DECKS; d++) {
/* calloc() here if you need the zero initialization */
arr[d] = malloc(sizeof(int) * DECKS);
}
foo(arr);
return 0;
}
*some compilers call such type like int (*)[20], but that isn't valid C syntax

C - function (Assume that a and n are parameters where a is an array of int values and n is the length of the array.)

I'm new to programming and I don't really understand this question. Can some of you give me examples of what it means. How do I write a function where a is int values and n is the length?
I'm confused...
I'm not sure what your question is, as you haven't provided much information. However, a function in C is defined like this:
return_type function_name( parameter list ) {
body of the function
}
So, for this situation, we could say:
void arrayFunction( int a[], int n){
//do whatever you need to do with the function here
}
This may help you some.
Suppose you have an array of ints, as follows:
int arr[] = {2,3,4,5,6};
You can see that there are 5 elements inside above array arr. You can count them.
But it happens that when you pass the above arr to function, that function has no idea about how many elements arr contains. See below (incorrect) code snippet:
#include <stdio.h>
void display(int arr[]){
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr);
return 0;
}
The function named 'display()' has no idea about how many elements arr has
Therefore you you need to pass the extra argument (the extra argument called 'n') to tell that called function about the number of elements inside arr. You need to tell this separately - the length of arr.
Now this becomes - as you said in your question - arr is int values and n is the length
Below is the correct code:
#include <stdio.h>
void display(int a[], int n){
//Now display knows about lenth of elemnts in array 'a'
// Length is 5 in this case
}
int main(void) {
int arr[] = {2,3,4,5,6};
display(arr, 5);
return 0;
}
Now, the function named 'display()' knows the length of array of int. This is the way you write code where you specify your array and its length.
More formally, this is because while passing array, it decays to a pointer and so the need arises to pass its length also alongwith it.

Segmentation fault (core dumped) when executing programs dynamically in c [duplicate]

This question already has answers here:
C sizeof a passed array [duplicate]
(7 answers)
Closed 4 years ago.
In the program below the length of the array ar is correct in main but in temp it shows the length of the pointer to ar which on my computer is 2 (in units of sizeof(int)).
#include <stdio.h>
void temp(int ar[]) // this could also be declared as `int *ar`
{
printf("%d\n", (int) sizeof(ar)/sizeof(int));
}
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", (int) sizeof(ar)/sizeof(int));
temp(ar);
return 0;
}
I wanted to know how I should define the function so the length of the array is read correctly in the function.
There is no 'built-in' way to determine the length inside the function. However you pass arr, sizeof(arr) will always return the pointer size. So the best way is to pass the number of elements as a seperate argument. Alternatively you could have a special value like 0 or -1 that indicates the end (like it is \0 in strings, which are just char []).
But then of course the 'logical' array size was sizeof(arr)/sizeof(int) - 1
Don't use a function, use a macro for this:
//Adapted from K&R, p.135 of edition 2.
#define arrayLength(array) (sizeof((array))/sizeof((array)[0]))
int main(void)
{
int ar[]={1,2,3};
printf("%d\n", arrayLength(ar));
return 0;
}
You still cannot use this macro inside a function like your temp where the array is passed as a parameter for the reasons others have mentioned.
Alternative if you want to pass one data type around is to define a type that has both an array and capacity:
typedef struct
{
int *values;
int capacity;
} intArray;
void temp(intArray array)
{
printf("%d\n", array.capacity);
}
int main(void)
{
int ar[]= {1, 2, 3};
intArray arr;
arr.values = ar;
arr.capacity = arrayLength(ar);
temp(arr);
return 0;
}
This takes longer to set up, but is useful if you find your self passing it around many many functions.
As others have said the obvious solution is to pass the length of array as parameter, also you can store this value at the begin of array
#include <stdio.h>
void temp(int *ar)
{
printf("%d\n", ar[-1]);
}
int main(void)
{
int ar[]= {0, 1, 2, 3};
ar[0] = sizeof(ar) / sizeof(ar[0]) - 1;
printf("%d\n", ar[0]);
temp(ar + 1);
return 0;
}
When you write size(ar) then you're passing a pointer and not an array.
The size of a pointer and an int is 4 or 8 - depending on ABI (Or, as #H2CO3 mentioned - something completely different), so you're getting sizeof(int *)/sizeof int (4/4=1 for 32-bit machines and 8/4=2 for 64-bit machines), which is 1 or 2 (Or.. something different).
Remember, in C when pass an array as an argument to a function, you're passing a pointer to an array.If you want to pass the size of the array, you should pass it as a separated argument.
I don't think you could do this using a function. It will always return length of the pointer rather than the length of the whole array.
You need to wrap the array up into a struct:
#include<stdio.h>
struct foo {int arr[5];};
struct bar {double arr[10];};
void temp(struct foo f, struct bar g)
{
printf("%d\n",(sizeof f.arr)/(sizeof f.arr[0]));
printf("%d\n",(sizeof g.arr)/(sizeof g.arr[0]));
}
void main(void)
{
struct foo tmp1 = {{1,2,3,4,5}};
struct bar tmp2;
temp(tmp1,tmp2);
return;
}
Inside the function ar is a pointer so the sizeof operator will return the length of a pointer. The only way to compute it is to make ar global and or change its name. The easiest way to determine the length is size(array_name)/(size_of(int). The other thing you can do is pass this computation into the function.

Create a C function that accepts parameters of different data types

I'm relatively new to the C programming language, and I'm trying to figure out how to create a function that can accept different types of data as parameters. The function is supposed to count and return the number of elements in a character or integer array. I already have two separate functions that will do this, but I would really like to be able to use one function for both tasks. Is there a way to do this in C?
Thanks in advance!
There is no standard function overloading in C (nor are there templates), but you could probably look into "printf-like" functions (or variadic functions) and maybe they can do what you need. If anything they allow for a flexible parameter list.
There is an example here of such a function that takes a variable size integer array.
Perhaps you could have a function signature such as void iterate(const char* format, ...); that you use in the following ways:
iterate("char", some_char_array); // for char arrays/strings
Or
iterate("int", some_int_array); // for integer arrays
Aniket makes a good point though, how do you count the elements in an integer array? If you pass an int array as an argument, you would need to pass the size too which defeats the purpose of counting the elements in the array (as you already know that i.e. the size).
I assume you don't know the size but you have a terminator value in the array (such as -1).
I've hacked something quick that kinda does what you need with the above assumption in mind.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
int iterate(const char* format, ...)
{
va_list ap;
va_start(ap, format);
if (strcmp(format, "char") == 0)
{
char* array = va_arg(ap, char*);
va_end(ap);
return strlen(array);
}
else if (strcmp(format, "int") == 0)
{
int j = -1;
int* int_array = va_arg(ap, int*);
while (int_array[++j] != -1)
;
va_end(ap);
return j;
}
va_end(ap);
return 0;
}
int main()
{
printf("%d\n", iterate("char", "abcdef"));
int arr[] = {5, 4, 3, 2, 1, 0, -1};
printf("%d\n", iterate("int", arr));
return 0;
}
This prints:
$ ./a.out
6
6
So, let's assume your two functions are called sizeof_char_array and sizeof_int_array.
In C11, there is a new feature called "generic selection" that will let you do what you want with a relatively simple macro:
#define sizeof_array(X) \
_Generic (*(X), \
char: sizeof_char_array, \
default: sizeof_int_array) (X)
(I don't even have a C11 implementation to test this against, so caveat emptor!)
Prior to C11, this was sometimes accomplished with a macro using regularly named functions. You can define a macro that will call one function or the other depending on a macro argument hint:
#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)
int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";
sizeof_array(int, a); /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b); /* macro expands to sizeof_char_array(b) */
If the input argument is truly an array, you can use a macro to compute its size directly:
#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))
In the case of an array, the following expression is true:
(void *)arr == &arr
Because the address of an array has the same location in memory as the address of its first element.
So, the macro computes: sizeof(arr)/sizeof(arr[0]). Since the sizeof operator reports the size in bytes of its argument, the computed expression results in the number of elements in the array. However, if you are using a sentinel to compute the length, the ARRAY_SZ macro will result in a size at least one larger than the length found traversing the array for the sentinel.
In the case that the argument is not an array, then the expression results in a divide by 0 exception.
The answer is quite simple. You do need a function for this task. Just try this piece of code
#define len(array) sizeof(array)/sizeof(*array)
and that's it.
Important note: As pointed out in the comments, this will not work for dynamically allocated arrays.
You should make your function arguments take in a void * type. This way, you can pass in different types of data, and type-cast it to the one you want. However, you do need to watch out because there is no guaranteed way to correctly 'guess' the type that a void* points to.
In either case, you will need some sort of type-inferencing system to tell the C compiler which function to call. Which means, you will need to know, before-hand the type of array you might send in as a parameter to this "super function" of yours.
There is no "auto-type-inferencing" in C that can let you reflect upon the type of data at runtime. Better yet, you might have to write your own runtime environment for this to happen.
A slightly trivial hackish way to do this:
#include <stdio.h>
size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes)
{
return sizeOfTheArrayInBytes/sizeOfOneElementInArray;
}
int main(int argc, char *argv[])
{
char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'};
int iArr[5] = {10,20,30,40,50};
printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)),
GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr)));
return 0;
}
It's not really possible, but you can make a tagged union
typedef struct {
union {
ssize_t i;
double d;
char *s;
} unknown;
char identity;
} Dynamic;
Or you can use a void pointer:
typedef struct {
void *unknown;
char identity;
} Dynamic;

All the array length methods in C don't work

I have tried (sizeof(array)/sizeof(array[0])). Didn't work.
I wrote a simple function:
int length(int array[]){
int i=0;
while(array[i]) i++;
return i;
}
Worked one minute, didn't work the next.
Someone please help! I'm using Xcode as an IDE
The length of an array is not part of the array in C, so when passing an array as a parameter to a function you should pass its length as a parameter too. Here's an example:
#define ARRLEN(a) (sizeof(a)/sizeof (a)[0]) /* a must be an array, not a pointer */
void printarray(int* a, int alen)
{
int i;
for (i = 0; i < alen; i++)
printf("%d\n", a[i]);
}
main()
{
int a[] = { 3, 4, 5 };
printarray(a, ARRLEN(a));
return 0;
}
However, if your array is defined in such a way as to always end with a sentinel that isn't normal data, then you can traverse the elements until you encounter the sentinel. e.g.,
void printstrings(char** a)
{
int i;
for (i = 0; a[i]; i++)
printf("%s\n", a[i]);
}
main()
{
char* a[] = { "This", "should", "work.", NULL };
printstrings(a);
return 0;
}
Passing an array into a function is the same as passing a pointer to the array.
So sizeof(array)/sizeof(array[0]) does not work.
You can define a global macro:
#define A_LEN(a) (sizeof(a)/sizeof(a[0]))
Try this
main()
{
int a[10] ;
printf("%d\n", sizeof(a)/sizeof(int) ) ;
}
output : 10
See Why doesn't sizeof properly report the size of an array when the array is a parameter to a function? from the comp.lang.c FAQ to understand why the sizeof method doesn't work. You probably should read the entire section on arrays.
Regarding your length function, your "simple" function can work only if your array happens to have the semantic that it is terminated with an element that has the value of 0. It will not work for an arbitrary array. When an array has decayed into a pointer in C, there is no way to recover the size of the array, and you must pass along the array length. (Even functions in the C standard library are not immune; gets does not take an argument that specifies the length of its destination buffer, and consequently it is notoriously unsafe. It is impossible for it to determine the size of the destination buffer, and it therefore cannot prevent buffer overflows.)
There are several methods to get the length of array inside a function (can be in the same file or in different source file)
pass the array length as a separate parameter.
make array length as global extern so that function can directly access global data

Resources