I need to implement a variable length data array containing void pointers. And I ran into the problem that when trying to print from this array I always output the last element.
Here is an abstract illustration of my problem and attempted implementation:
#include <stdio.h>
#include <stdlib.h>
int main() {
int capacity = 4; // for example
void **array = malloc(capacity*sizeof(void*));
// assign values to array elements
for(int i = 0; i < capacity; i++) {
array[i] = malloc(sizeof(void*)); // not sure if it necessary
int a = i*i;
array[i] = &a;
printf("index: %d, element: %d\n", i, *(int*)array[i]); // for demonstration
}
printf("\n");
/*
* after that I try to print all the elements of the array sequentially
*/
for(int i = 0; i < capacity; i++) {
printf("index: %d, element: %d\n", i, *(int*)array[i]));
}
// I know that I do not free my memory, but that’s not the point
return 0;
}
Output that i get looks like:
index: 0, element: 0
index: 1, element: 1
index: 2, element: 4
index: 3, element: 9
index: 0, element: 9
index: 1, element: 9
index: 2, element: 9
index: 3, element: 9
(Edit the questions: in the comments they pointed out to me that the error was in the way of putting the variable in the mass, because I did not take into account the lifetime of the variable in the for-loop and the principle of the pointer)
How can I correctly fill a similar array without introducing a bunch of extra variables? Or the method that I chose is completely incorrect?
I would be grateful for any help
You see the "last element", because a stays at the same position of the stack in each iteration, and thus &a stores that particular single address into all elements. Then the address contains the last value written there - until it becomes complete garbage when anything else overwrites it.
You would need different addresses, so you would need to allocate memory for each number, inside the loop. Which kind of happens already, just you allocate memory for a void*, while you would need an int, and you overwrite it, which (as the comments point out already) you simply should not do:
array[i] = malloc(sizeof(int));
*(int*)array[i] = i*i;
printf("index: %d, element: %d\n", i, *(int*)array[i]); // for demonstration
Then it works: https://ideone.com/dF4KY8 (an extra ) has been removed from the end)
Of course, you would need to free() stuff, as your own comment suggests.
I hope, I can help you.
malloc reserves space (as you probably already know) and returns a void*, not a void**. I would initialize it with:
const int capacity = 4;
int* array = (int*)malloc(capacity*sizeof(int));
I wouldn't initialize the array as void** because you plan to store many ints in
it and an int array is nothing else than an int*.
If you already initialize the array in the beginning you have not to
call malloc again. 'malloc', returns the address, where the memory is allocated
for you but you already know, where you want to store the data. If you have a
void**, it is a multidimensional array. One thing left: On failure malloc returns a null-pointer a check whether the array is null, wouldn't harm you. :)
There is a ')' too much within the printf();
Related
How does sizeof() calculate that array1 is 3 bytes instead of 4 since I assigned a value to the 4th byte of memory allocated to the array?
#include <stdio.h>
char array1[3] = { 0,0,0 };
char array2[4] = { 0,0,0,0 };
char* a1 = array1;
char* a2 = array2;
int main(void) {
printf("Array 1 Memory: %p\n", a1);
printf("Array 2 Memory: %p\n\n", a2);
//Array 1 set values and display addresses.
printf("array1 = [");
for (int i = 0; i < 5; i++) {
array1[i] = i;
printf("%d, ", array1[i]);
}
printf("\n");
for (int i = 0; i < 4; i++) {
printf("array1[%d] memory location: %p\n",i, a1 + i);
}
printf("size of array1 = %d\n", sizeof(array1));
printf("]\n");
//Array 2 display values and addresses
printf("array2 = [");
for (int i = 0; i < 4; i++) {
printf("%d, ", array2[i]);
}
printf("\n");
for (int i = 0; i < 4; i++) {
printf("array2[%d] memory location: %p\n", i, a2 + i);
}
printf("size of array2 = %d\n", sizeof(array2));
printf("]\n");
printf("array2[-1] = %d\n", array2[-1]);
return 0;
}
Array 1 Memory: 005CA4F4
Array 2 Memory: 005CA4F8
array1 = [0, 1, 2, 3, 4,
array1[0] memory location: 005CA4F4
array1[1] memory location: 005CA4F5
array1[2] memory location: 005CA4F6
array1[3] memory location: 005CA4F7
size of array1 = 3
]
array2 = [4, 0, 0, 0,
array2[0] memory location: 005CA4F8
array2[1] memory location: 005CA4F9
array2[2] memory location: 005CA4FA
array2[3] memory location: 005CA4FB
size of array2 = 4
]
array2[-1] = 3 //3 is stored in this location, so all bytes in the 4 byte word have a value in them. So
//how does sizeof(array1) return a value of 3 instead of 4. How does it "remember" that only 3 bytes were
//originally assigned to the array?
I looked for the declaration for the sizeof function in stdio header and couldn't find it. I thought that if I could see how sizeof() determines the size of an array, then it would give me some insight to my question. I'd like to know where sizeof() can be found.
Where is the source code for the C compiler that I can refer to in order to learn what an array actually is and how its size is stored in memory? If I create a char array[3], then a char[3] object is created, right? How is the char[3] object created? How does the system "remember" that the array should only be 3 bytes?
Some useful links (highly recommended):
sizeof operator
Queries size of the object or type
Used when actual size of the object must be known
In C, there is no object creation per se but a definition of an declared object, more here:
Declarations
A declaration is a C language construct that introduces one or more identifiers into the program and specifies their meaning and properties.
Definitions
A definition is a declaration that provides all information about the identifiers it declares.
and
Array declaration
Array is a type consisting of a contiguously allocated nonempty sequence of objects with a particular element type. The number of those objects (the array size) never changes during the array lifetime.
and
Array initialization (e.g. Initialization from brace-enclosed lists)
sizeof(array1) tells you how many bytes of memory were reserved for the object array1. It does not tell you how many bytes you attempted to store into it.
char array1[3] = { 0,0,0 }; reserves three bytes for array1.
array1[i] = i; attempts to write a byte to array1[i]. The C implementation generally does not check whether you are staying within the reserved memory or not. If you do not stay within the memory reserved for the array, the behavior is not defined by the C standard.
Using array1[i] = i; to write to memory outside the array does not change the reservation.
A source of confusion for beginners is seeing sizeof() with parentheses and presuming it is a runtime function. It is not a runtime function. It is a "compile time" operator.
Parentheses are required when taking the size of a datatype:
eg: sizeof( char ) or sizeof( struct foobar ).
Parentheses are optional when taking the size of an item the compiler has already "seen" in the current "compilation unit" (typically meaning the current source file being compiled.) For example:
double a;
size_t size_of_a = sizeof a; // parentheses not required here.
Imagine that the expression "sizeof a" above is replaced with the value 8 (being the number of bytes used to store a single double floating point number in many compilers.)
The compiler has had to "measure" the storage requirements for your array. During compilation, the compiler "knows" the extent of that allocation and can quickly replace sizeof myarray with the correct value.
So, I have an array containing 1 value. And then I copy(assign) it to another array. But, if I change the value on the second array, the value of first array got changed too. This is my code:
#include <stdio.h>
void change(int a[]){
int *temp = a;
for(int i=0; i<2; i++){
a[i] = temp[0]*10+7;
}
//What I expect for the result is a[0] = 7, a[1] = 7 instead of a[0] = 7, a[1] = 77
}
int main(){
int num[1];
num[0] = 0;
change(num);
printf("%d", num[0]);
return 0;
}
What happen to my array?
EDIT : I want to copy the value, not the address of array
EDIT 2: I have change a little bit of my code above to make it more clear what I want.
"But, if I change the value on the second array, the value of first array got changed too"
Array is not passed as copy (arrays not passed by values) - it is a pointer pointing to an address where the first element is in memory. Therefore, you are actually modifying the values (arrays passed by reference)
Be aware ! When passing an array as a parameter :
void func(int a[])
means exactly the same as :
void func(int *a)
First, this declaration
void change(int a[]);
is equivalent with this declaration
void change(int *a);
Second (see this link for more info),
The C language is pass-by-value without exception. Passing a pointer
as a parameter does not mean pass-by-reference.
So you are passing a copy of the pointer's address (which points to the same array/address). Then you merely dereference the array's first position and assign a value to it (this really is just pointer arithmetic here).
Maybe it helps to rewrite the code in order to make the pointer arithmetic more obvious:
#include <stdio.h>
void change(int *a){
int temp[1];
*(temp+0) = *(a+0);
*(a+0) = *(temp+0) * 10 + 7;
}
int main(){
int num[1];
*(num+0) = 0;
change(num);
printf("%d", *(num+0));
return 0;
}
I am not sure how to understand the EDIT
EDIT : I want to copy the value, not the address of array
Looking at the code I fail to understand what you might want to try to achieve with this. Please clarify on this.
Having read your clarification I understand that you do not want to modify the array elements in the main function yet modifying them in the change function.
The answer is you cannot do that. The explanation is as mentioned above. I suggest you take some time to learn about pointer arithmetic and arrays in C. The K&R book is really excellent in that regard; I really recommend the book.
What you could do is copy the content of the array into another array and modify that one; e.g. in the beginning of the function or before calling the function and passing that copied array as parameter.
In c arrays are passed by reference. Meaning you are not passing the value but the adress where the elements of array are stored.
When you assign value to a[0] in a function, you are actually updating the num array.
When you use just an array's name to pass to a function, you actually create a temporary pointer to the first element of your array. So, your change() function receives as a copy of that temporary pointer the address of your num[] array in main.
The whole concept is called 'passing by reference'.
If you want to pass a copy of an array to a function in C, you may put the array into a struct and pass this struct by value, e.g.
struct s {
int a[4];
};
void change(struct s elem)
{
elem.a[0] = 1; //assigment to copy
}
If you want to make a copy of an array inside a function so that you can work on the array copy without changing the original array, the best option is to make an explicit copy of the array yourself.
The most portable way to do this is by using malloc() or calloc() to allocate memory, and then copying the contents of the original array to the new memory allocation. If you choose this path your code must be sure to free any dynamically allocated memory when it is no longer needed. The copying can be done by looping and using array index notation to access the allocated memory, or by using memcopy() to copy the contents of the original array. Another option is to use a Variable Length Array (added to C with C99, made optional in C11 and C17 but still widely supported) to avoid dynamically allocating and deallocating the memory yourself.
Here is an example program that contains two functions, work_on_copy() and work_on_copy_vla(), that each take an array, copy it, and do some work that changes the copy. A final argument provides an array index which is used to illustrate how the array copy can be used to modify the original array selectively after work has been done inside the function. If this argument is a valid array index, the value at that index is copied from the array copy to the original array.
Note that this problem could also be solved by wrapping an array in a struct, but this method has the disadvantage of requiring that the array member of that struct be the same size as the largest array that is expected, wasting memory in the general case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(size_t arr_sz, int arr[]);
void work_on_copy(size_t arr_sz, int arr[], int index);
void work_on_copy_vla(size_t arr_sz, int arr[], int index);
int main(void)
{
int my_arr[] = { 1, 2, 3, 4 };
size_t my_arr_sz = sizeof my_arr / sizeof *my_arr;
puts("-- Do not change original array at all --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, -1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
putchar('\n');
puts("-- Change specified index of original array after work --");
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy(my_arr_sz, my_arr, 1);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
work_on_copy_vla(my_arr_sz, my_arr, 3);
printf("Array in main(): ");
print_array(my_arr_sz, my_arr);
return 0;
}
void print_array(size_t arr_sz, int arr[])
{
for (size_t i = 0; i < arr_sz; i++) {
printf("%d ", arr[i]);
}
putchar('\n');
}
void work_on_copy(size_t arr_sz, int arr[], int index)
{
/* make copy of array: could return a pointer to this allocation */
int *arr_copy = malloc(sizeof *arr_copy * arr_sz);
/* handle error if allocation fails */
if (arr_copy == NULL) {
perror("unable to allocate memory");
return;
}
memcpy(arr_copy, arr, sizeof *arr_copy * arr_sz); // or use a loop
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] += 10;
}
printf("Array copy after work (malloc): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
/* deallocate memory to avoid memory leaks */
free(arr_copy);
}
void work_on_copy_vla(size_t arr_sz, int arr[arr_sz], int index)
{
/* make local copy of array using a VLA */
int arr_copy[arr_sz];
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] = arr[i];
}
/* do work on local copy */
for (size_t i = 0; i < arr_sz; i++) {
arr_copy[i] *= 2;
}
printf("Array copy after work (VLA): ");
print_array(arr_sz, arr_copy);
/* update original array if needed */
if (index >= 0 && (size_t)index < arr_sz) {
arr[index] = arr_copy[index];
}
}
Program output:
-- Do not change original array at all --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 2 3 4
Array copy after work (VLA): 2 4 6 8
Array in main(): 1 2 3 4
-- Change specified index of original array after work --
Array in main(): 1 2 3 4
Array copy after work (malloc): 11 12 13 14
Array in main(): 1 12 3 4
Array copy after work (VLA): 2 24 6 8
Array in main(): 1 12 3 8
I am new to C and was writing a function to insert an element to sorted list. But my code does not display the last digit correctly. Though i know there are variety of ways to correct it but i want to know why my code isnt working, here's the code
#include <stdio.h>
int insert(int array[],int val);
int main (void)
{
int arr[5],j;
for (j = 0; j<5; j++)
{
scanf("%d",&arr[j]);
}
insert(arr,2);
for(j = 0;j<6;j++)
printf("%d",arr[j]);
return(0);
}
int insert(int array[],int val)
{
int k,i;
for (k = 0;k<5;k++)
if(val<array[k])
break;
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
}
array[k] = val;
return(1);
}
You are writing out of the range of the array here:
for (i = 4; i>=k;i--)
{
array[i+1] = array[i];
Where i+1 == 5 and you array has a range of 0 ...
4
Then you try to print the array but you go out of bounds again:
for(j = 0;j<6;j++)
printf("%d",arr[j]);
First make sure your array is large enough.
When you give a static / auto array to a function for insertion of elements, you must give: Address, Valid length, and Buffer Space unless guaranteed large enough.
When giving a dynamically allocated array, you must give pointer and valid length, you might give buffer space or guarantee enough space left to avoid reallocations.
Otherwise, you risk a buffer overrun, and UB means anything may happen, as in your example.
You're trying to make arr[6] out of arr[5] adding one val - it's impossible in C using statically allocated arrays.
To accomplish what you're trying to do you'd need to use dynamical arrays allocation:
int *arr;
int N = 5;
arr = (int *)malloc(N*sizeof(int));
then you use this arr same way as you did with arr[5] for loading data here via scanf.
And later on , while adding extra value to array - you'd need to reallocate your arr to make it bigger (read about malloc/realloc C functions):
arr = (int *)realloc((N+1)*sizeof(int));
Now your arr is of 6 int-s size.
Unfortunately if you don't know array sizes (number of elements) a priori you would need to deal with dynamical memory allocations in C.
Don't forget to release that memory in the end of the main() function:
free(arr);
You have to increase your array size from 5 to 6 as you are inserting one new element in your array, so there should be some space for that.
int arr[6];
you can also find more information in the link below:
https://learndswithvishal.blogspot.com/2020/06/insert-element-in-sorted-array.html
I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.
The exercise says "Create a function with two parameters a and b which are integers and the function will return an array of integers with every number from a to b.
#include <stdio.h>
#include <stdlib.h>
void exc(int a, int b){
int i,k=0,d[k];
for(i=a;i<=b;i++){
d[k]=i;
k++;
printf("%d ",d[k]);
}
}
int main(void){
int c,d;
printf("Give first integer: ");
scanf("%d",&c);
printf("Give second integer: ");
scanf("%d",&d);
exc(c,d);
system("pause");
}
The problem is that if I put for example c=2 and d=5 the program returns something like 2088806975 16384 1 2293536 instead of 2 3 4 5. Where is the problem? Thanks
For starters
If your main() has return type int, don't forget to return a value from it!
int main(void)
{
/* code here */
return 0;
}
Problem 1
By
d[k]=i;
k++;
printf("%d ", d[k]);
I think you meant
d[k]=i;
printf("%d ", d[k]);
k++;
otherwise you're printing the "next" array element each time, which will be one-past-the-end of the array on the last loop iteration.
Problem 2
int i,k=0,d[k];
You make an array d of size k where k is 0. I think you intended for the array to automatically resize when you write k++, but this is not the case. The array is created with zero elements, and then that's its size for all time.
Your next instinct may be to create the array big enough in the first place:
int d[b-a+1];
Unfortunately, this is most likely wrong, too. It relies on a feature called Variable Length Arrays (or "VLAs"); although a GCC compiler extension (and, incidentally, C99) does allow this (and it's not clear whether you have that extension enabled and/or are allowed to use it in your homework — I will assume for this answer that you do not / are not), the language itself does not allow an array with a dynamic size.
What do I mean by dynamic size?
I mean that the variables a and b depend on user input: they are not known at compile-time. In general, the size of an array must be known at compile-time.
Note: If you use this, your code may compile without error, and your program may even appear to run and work correctly. However, you'd be relying on what's called "Undefined Behaviour", and your code could stop running or even crash at any time, due to any number of random, unpredictable factors. Even if it looks like it's okay, it's invalid. Don't do it!
Solution
Fortunately, there is a way to allocate a block of memory with the right size for your elements, when you don't know the elements until your program runs. It's called "dynamic allocation", and it involves a function call:
int *d = malloc(sizeof(int) * (b-a+1));
You can use the same syntax (d[k]) to access "elements" in this "array" or block of memory, but you must later manually free the memory:
free(d);
Possible problem 3
Your assignment says to return an array from the function, but you're not doing this. Instead, you're just creating, filling and printing the array all within the same function (which seems a bit pointless).
You can't actually return an array either, but since you're dynamically allocating the space for it, you have a pointer to work with. It's my opinion that your teacher may have wanted you to return a pointer to this array.
If so, the finished code looks a bit like this:
#include <stdio.h>
#include <stdlib.h>
int *exc(int a, int b)
{
int i, k = 0;
int *d = malloc(sizeof(int) * ((b-a)+1));
for (i=a; i<=b; i++) {
d[k]=i;
k++;
}
return d;
}
int main(void)
{
int a,b,i,*ar;
printf("Give first integer: ");
scanf("%d",&a);
printf("Give second integer: ");
scanf("%d",&b);
ar = exc(a,b);
for (i=0; i < (b-a+1); i++) {
printf("%d ", ar[i]);
}
free(ar);
system("pause");
return 0;
}
Disclaimer: I'm rusty on C, so the finished code might have a few syntax bugs.
Hope this helps!
The size of d is always 0. Since you are initializing it as d[k]. You should instead do something like d[b-a+1].
Update:
Furthermore, the order of your statements are wrong, see pmg's answer.
Update 2:
Your code doesn't actually return the array you are creating and it won't work unless you create the array on the heap (ie. using malloc / free).
The order of statements is not correct
d[k]=i; // d[0] = 42;
k++; // ...
printf("%d ",d[k]); // print d[1]
You need to allocate the memory for the array first, use malloc with the amount of integers you need to assign
Also, to be true to the problem statement, have the function return a pointer to the array so the main function can print it out instead of the exec function doing it directly.
Doing somebodys homework is always somewhat bad but obviously OP has no idea how to aproach this particular problem so here is a full example of dynamic memory allocation (overly commented).
#include <stdio.h>
#include <stdlib.h> /* required for malloc() and free() */
/* function that retuns a pointer to int type of data */
int *create_array(int a, int b)
{
int *array;
int array_size = b - a + 1; /* assuming that 'a' is always smaller than 'b' */
int i;
array = malloc( array_size * sizeof(int) ); /* allocate memory for the array */
if(array == NULL) exit(EXIT_FAILURE); /* bail out if allocation fails */
/* assign the values into array */
for(i = 0; i < array_size; ++i)
array[i] = a++;
/* return a pointer to our allocated array */
return array;
}
int main(void)
{
int *array;
int i, a = 42, b = 50;
/* and now we can call the function to create the array */
array = create_array(a, b);
/* print results */
for(i = 0; i < b - a + 1; ++i)
printf("%d\n", array[i]);
/* always remember to free the data after you are done with it */
free(array);
return 0;
}
You incorrectly declare d array in your code:
int d[k];
should be:
int d[b-a+1];
Edit::
Also, as others have posted, the statement order is wrong:
d[k]=i;
k++;
printf("%d ",d[k]);
should be:
d[k]=i;
printf("%d ",d[k]);
k++;
because otherwise you "lose" the first value when k==0.
You made an array of size zero and then started throwing data in without resizing the array. I'm a bit surprised that you aren't getting an error.
You're accessing data from memory outside the safety of defined data storage. It should be an error because the results are not defined. The data past the end of your array could be used for anything. And since your array is size zero, everything is past the end.
There are a couple problems. First, d is not returned from exc. Of course, you shouldn't just return it since it's allocated on the stack. Secondly, the printf is called after you increment k. That prints the next element in d, not the one whose value you just filled in. Finally, d doesn't have any space allocated for it, since k is always 0 when d is created.
It happens because you allocate memory for d on the stack. If you move the declaration of it outside the function, everything shoud be ok.