I'm learning C, and tried writing a function that, given an array of integer, returns the length of the array. Here is my code:
#include <stdio.h>
int length_of_array(int array[])
{
int length = 0;
int i = 0;
while (array[i] != '\0') {
length += 1;
i += 1;
}
return length;
}
int main()
{
int test_array[] = {1, 2, 3, 4, 5};
printf("%d\n", length_of_array(test_array));
return 0;
}
However, when I compile this code and run it, I says that the length of the array passed in is 14. Does anyone know what could be the problem here?
Strings in C are NUL-terminated. Arrays are not (unless you explicitly do it yourself). The size of array is just the size of array: if allocated as a constant, you can find out the size with sizeof operator. If all you have is a plain pointer, you need to remember the size - there is no way in C to get it once you forget it.
#include <stdio.h>
int main() {
int test_array[] = {1, 2, 3, 4, 5};
int *test_ptr = test_array;
printf("%lu\n", sizeof(test_array) / sizeof(*test_array)); // correct
printf("%lu\n", sizeof(test_ptr) / sizeof(*test_ptr)); // incorrect
return 0;
}
Related
I am not sure why I am not getting a display on the console for the value of maxProd. I think I am declaring the arr_integer array variable wrong in main?
I ran a couple tests and the program looks like it does not even get to call solution().
Any help would be greatly appreciated. I am trying to get this to work and get rid of the following warnings;
Adjacent_Element_Product.c:31:40: note: (near initialization for 'array')
Adjacent_Element_Product.c:31:43: warning: excess elements in struct initializer
#include <stdio.h>
typedef struct arr_integer {
int size;
int *arr;
} arr_integer;
arr_integer alloc_arr_integer(int len) {
arr_integer a = {len, len > 0 ? malloc(sizeof(int) * len) : NULL};
return a;
}
int solution(arr_integer inputArray) {
int maxProd = inputArray.arr[0] * inputArray.arr[1];
for (int i = 1; i < inputArray.size - 1; i++)
{
int product = inputArray.arr[i] * inputArray.arr[i + 1]; //multiple next door neighbours.
if (product > maxProd)
maxProd = product;
}
return printf("maxProd: %d\n", maxProd);
}
int main()
{
arr_integer array = {3, 6, -2, -5, 7, 3};
solution(array);
return 0;
}
The problem is that you don't allocate memory for the array and that it then tries to use the list of integers as an int*.
A possible remedy:
#define Size(x) (sizeof (x) / sizeof *(x))
int main() {
int ints[] = {3, 6, -2, -5, 7, 3};
arr_integer array = {.size = Size(ints), .arr = ints};
solution(array);
}
Here are the relevant changes:
added <stdlib.h> for malloc
eliminated alloc_arr_integer() which was not used
maxProd is initialized to INT_MIN and tweaked initial loop condition to reduce duplication
to make the solution a little smaller passing the value inline to solution (#TedLyngmo probably gave you a better solution)
Not fixed:
arr_integer doesn't seem to add any value so maybe just pass size and array to solution(). You could create a macro to initialize it using the approach #TedLyngmo shared with you. It has to be a macro as int [] degrades to int * in a function call, and the latter (silently?) gives you the wrong result which makes it error prune.
Does negative size make sense? If not then use an unsigned type.
What is the solution if size < 2?
solution() returns the value from printf() which is strange. You might want to return maxProd and have main() print out the value. This makes your function testable
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct arr_integer {
int size;
int *arr;
} arr_integer;
int solution(arr_integer inputArray) {
int maxProd = INT_MIN; // what is answer if size < 2? error?
for (int i = 0; i < inputArray.size - 1; i++) {
int product = inputArray.arr[i] * inputArray.arr[i + 1]; //multiple next door neighbours.
if (product > maxProd)
maxProd = product;
}
return printf("maxProd: %d\n", maxProd);
}
int main() {
solution((arr_integer) {
6,
(int []) { 3, 6, -2, -5, 7, 3 }
});
return 0;
}
and the output is:
maxProd: 21
i have my length function to calculate the length of array, but it is giving two excess garbage numbers(negative). It must return 6 but it returns 8 due to garbage values.
#include<stdio.h>
int length(int *arr) {
int _length = 0;
while (*arr) {
_length++;
arr++;
}
return _length;
}
int main() {
int arr[] = {2, 1, 3, 4, 5, 6};
printf("%d\n", length(arr));
return 0;
}
You need some manner of termination condition. while (*arr) assumes that the array ends with zero which isn't the case, so you simply can't have a loop like that.
The size of this array is known at compile time so there's no need to calculate anything in run-time.
(sizeof arr / sizeof *arr) gives you the number of items in the array, as long as you place that code in the same scope as the array declaration.
Also, using that sizeof trick (which is an idiomatic way of determining the size) inside a function-like macro is a common solution:
#include <stdio.h>
#define length(arr) (sizeof(arr)/sizeof(*arr))
int main() {
int arr[] = {2, 1, 3, 4, 5, 6};
printf("%zu\n", length(arr));
return 0;
}
#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.
I'm working in C, and am attempting to replicate the length member function that other languages (ie: C++) use to determine the length of an array or possibly vector of data. Is this something I can accomplish in C, or do I have to fall back onto examples like this:
int arraySize = sizeof(array) / sizeof(array[0]);
In general, in C, you use arrays as they are: a contiguous set of multiple pieces of data of the same type. You are generally expected to keep track of array sizes, along with the size of individual members, yourself.
In C++, for example, you have access to the Vector class, which encapsulates and handles all this record keeping for you.
In C, you would be expected to know exactly how big the array is. This is especially important in the case of pointer decay. Your initial example...
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = sizeof(arrayOfInts) / sizeof(int); // Success; Returns "6"
This works in this case, but it will fail if you were to pass the array to a function expecting an array of integers (as a pointer) as a function argument.
#include <stdio.h>
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[6] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
int ret;
ret = sizeof(arr) / sizeof(int); // FAILS, returns the size of a pointer-to-int, not the size of the array
return ret;
}
There are two ways to handle this: static definitions, or careful dynamic memory management.
// CASE 1: Trivial case, all arrays are of a static fixed size
#include <stdio.h>
#define ARR_SIZE (6)
int getArraySize(int* arr);
int main(void) {
int arrayOfInts[ARR_SIZE] = {1, 2, 3, 4, 5, 6};
int sizeOfArray = getArraySize(arrayOfInts);
return 0;
}
int getArraySize(int* arr) {
return ret ARR_SIZE;
}
// CASE 2: Managing sizes with dynamic allocation
#include <stdio.h>
#define ARR_SIZE (6)
int main(void) {
int sizeOfArray = ARR_SIZE;
int* arrayOfInts = malloc(sizeOfArray*sizeof(int));
if (arrayOfInts != NULL) {
// Success; initialize
int i;
for (i=0; i<sizeOfArray; i++) {
arrayOfInts[i] = i;
}
return 0;
} else {
// Failed; abort
sizeOfArray = 0;
return (-1);
}
}
If this is possible:
#include <stdio.h>
#include <process.h>
#define SIZE 5
void PassingArray(int arr[])
{
int i=0;
for(i=0 ; i<SIZE ; i++)
{
printf("%d, ", arr[i]);
}
printf("\n");
}
main()
{
int myIntArray[5] = {1, 2, 3, 4, 5};
PassingArray(myIntArray);
system("PAUSE");
}
Then why the following is illegal?
#include <stdio.h>
#include <process.h>
#define SIZE 5
int ReturningArray()[]
{
int myIntArray[5] = {1, 2, 3, 4, 5};
return myIntArray;
}
main()
{
int myArray[] = ReturningArray();
system("PAUSE");
}
You're not returning an int, but you're returning the array. This is the same value as &myIntArray[0]. int ReturningArray()[] is not a valid function prototype.
There's multiple reasons why this doesn't work.
The first is simply that it's prohibited by the language - the return type of a function shall not be an array (it also can't be a function).
The second is that even if you were allowed to declare ReturningArray as you do, you could never write a valid return statement in that function - an expression with array type that is not the subject of the unary & or sizeof operators evaluates to a pointer to the first element of the array, which no longer has array type. So you can't actually make return see an array.
Thirdly, even if we somehow had a function returning an array type, you couldn't use that return value as the initialiser of an array variable - the return value would again evaluate to a pointer to the first element of the array: in this case a pointer to int, and a pointer to int isn't a suitable initialiser for an array of int.
There are several problems with this code.
You are placing the brackets at the wrong place. Instead of
int ReturningArray()[]
it should be
int* ReturningArray()
You are returning a local variable. Local variables only exist during the execution of the function and will be removed afterwards.
In order to make this work you will have to malloc the int array and return the pointer to the array:
#include <stdio.h>
#include <malloc.h>
#define SIZE 5
int* ReturningArray()
{
int *myIntArray = (int *)malloc(SIZE * sizeof(int));
myIntArray[0] = 1;
myIntArray[1] = 2;
myIntArray[2] = 3;
myIntArray[3] = 4;
myIntArray[4] = 5;
return myIntArray;
}
int main(void)
{
int i;
int* myArray = ReturningArray();
for(i=0;i<SIZE;i++) {
printf("%d\n", myArray[i]);
}
free(myArray); // free the memory again
system("PAUSE");
return 0;
}
PassingArray is legal, but it does not pass an array. It passes a pointer to the first element of an array. void PassingArray(int arr[]) is a confusing synonym for void PassingArray(int *arr). You can't pass an array by value in C.
ReturningArray is not allowed, you can't return an array by value in C either. The usual workaround is to return a struct containing an array:
typedef struct ReturnArray {
int contents[5];
} ReturnArray;
ReturnArray ReturningArray()
{
ReturnArray x = {{1, 2, 3, 4, 5}};
return x;
}
Arrays are second-class citizens in C, the fact that they can't be passed or returned by value is historically related to the fact that they can't be copied by assignment. And as far as I know, the reason for that is buried in the early development of C, long before it was standardized, when it wasn't quite decided how arrays were going to work.
You can't return array from a function, but It is possible that you can declare a function returning a (reference in C++) or pointer to array as follows:
int myIntArray[] = {1, 2, 3, 4, 5};
int (*ReturningArray())[sizeof(myIntArray)/sizeof(int)] {
return &myIntArray;
}