tags:

views:

127

answers:

8

I'm a novice user of C language. I have a problem in allocating a dynamic array.

I used to allocate memory outside the loop such as a=(int*)malloc(5* sizeof(int)); and every thing worked fine. Now I want to allocate memory to each element one by one in a loop using malloc(), but the code is not working.

I've tried different options like scanf("%d",a) &a++,scanf("%d",&a[i]); etc but could not succeed. If anyone can tell me what I was doing wrong and explain to me the concept thoroughly, I'll be thankful.

The code which I'm having problems with is the following:

#include <stdio.h>
#include<stdlib.h>

int main()
{
  int *a;
  int i;
  system("clear");

  for(i=0;i<5; i++)
  {
    a=(int *)malloc(sizeof(int));
    printf("%u",&a);
    printf("please enter the element in array");
    scanf("%d",a[i]);
  }
  for(i=0;i<5; i++)
  {
    printf("\nthe %d entry in the array %d",i,a[i]);
  } 
  return 0;
}
+1  A: 

In each iteration your code overwrites the old value of a. So you lose the address of the previously mallocated memory.

Each malloc allocates only sapce for one int. It's illegal to dereference the pointer with an index > 0. That's why your code gives undefined behaviour.

harper
thankx for help now i understand it completly
manish
A: 

The problem is that you create a new array with size = 1 everytime in the for loop.

So everytime "a" has place for one integer.

kafbuddy
thanx 4 help but is there any way that i can give memory to each element explicitly in a for loop
manish
A: 

The whole thing is, to be honest, a disaster. If you are learning and are completely confused, try reading up on C pointers.

Look, perhaps try something like this:

#include <stdio.h>
#include <stdlib.h>

int main()
{
int *a;
int i;
system("clear");

a=(int *)malloc(sizeof(int)*5);

for(i=0;i<5; i++)
{
  printf("please enter the element in array");
  scanf("%d",a+i);
}

for(i=0;i<5; i++)
{
  printf("\nthe %d entry in the array %d",i,a[i]);
}

return ;
}

Or the way I would do it:

#include <vector.h>
#include <stdio.h>

int main()
{
  vector<int> a;
  int i;
  system("clear");

  for(i=0;i<5;i++)
  {
    printf("please enter the element in array");
    int n;
    scanf("%d",&n);
    a.push_back(n);
  }

  for(i=0;i<5; i++)
  {
    printf("\nthe %d entry in the array %d",i,a[i]);
  }

  return ;
}

You see, you cannot simply allocate new memory and expect to be "added" to previously allocated memory. The only way to add to or resize a block of memory is to recreate it, and carry over the data.

Alexander Rafferty
Is vector.h C? Looks like this is C++ to me.
Sorpigal
Vector is a part of STL and it's a C++ solution indeed.
rhino
It's the way I would do it, and the way I would do it is in C++. I don't know why any one knew to the trade would learn C instead of C++ (unless it was for background, for example: learning objective-c, c#, ect...)
Alexander Rafferty
thanx but it is not vector it just a one dimensional array,by the like ur honesty in saying that the whole thing is a disaster
manish
@Alexander: if the question had a C++ tag, you would be OK. It doesn't; your answer is inaccurate - whatever you think about C versus C++. If you wish to survive on SO, respect the tags.
Jonathan Leffler
I posted a C answer aswell, mind you.
Alexander Rafferty
+5  A: 

An array is a single "object" (a single thing) that has space for many items, all of the same type.

Your expectation to be able to somehow allocate one item at a time is incorrect, that's simply not how arrays work.

You should do like you first said, a single malloc() allocating room for 5 items, and then just store each one to its proper position in the array inside the loop.

I would recommend using scanf("%d", &a[i]) to read and store into the array. There are other ways of writing the second argument, but this (in my opinion) is the clearest and best for a beginner. It reads as "the address of the i:th item in the array a".

unwind
thanx for help pal this is the best answer for me i wont try to do it again thanx pal
manish
A: 

unwind's answer is the explanation, but here's some code to demonstrate

#include <stdio.h>
#include <stdlib.h>

int main(){
    int *a;
    int size = 5;
    int i = 0;
    a = malloc(sizeof(int)*size);

    for(i=0;i<size;i++){
            printf("%u: ",&a);
            printf(" please enter the element in the array> ");
            scanf("%d", &a[i]);
    }

    for(i=0;i<size;i++){
            printf("index %d in the array is %d\n",i,a[i]);
    }

    free(a);

    return 0;
}
Sorpigal
thanx pal but i did it already
manish
+1  A: 

a[i] is equivalent to *(a+i)

scanf needs the address of a which can be supplied here by using &(a[i]) or simply (a+i). Instead, you are passing it a[i], which refers to data stored at the location (a+i).

Kedar Soparkar
Yes, the other answers seem to have missed this for some reason...
wj32
manish
+1  A: 

As everyone has pointed out, you really don't want to allocate each element of the array separately. However, if, despite the advice, you decide you do, then you need both an array of pointers and the individual pointers:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
enum { ARRSIZE = 5 };

static void err_exit(const char *msg)
{
    fprintf(stderr, "%s\n", msg);
    exit(1);
}

int main()
{
  int **a;
  int i;
  a = (int **)malloc(sizeof(*a)*ARRSIZE);
  if (a == 0)
      err_exit("out of memory");

  for (i = 0; i < ARRSIZE; i++)
  {
    a[i] = (int *)malloc(sizeof(int));
    if (a[i] == 0)
        err_exit("out of memory");
    printf("%" PRIuPTR "\n", (uintptr_t)a[i]);  // Print allocated address
    printf("please enter the element in array: ");
    if (scanf("%d", a[i]) != 1)
        err_exit("failed to read a valid integer");
  }
  for (i = 0; i < ARRSIZE; i++)
  {
    printf("the %d entry in the array %d\n", i, *a[i]);
  }
  return 0;
}

Additional points:

  • Check that malloc() worked.
  • Using scanf() can lead to a world of pain. You should check its return status too. If you type a letter instead of a digit, your code will fail rather horribly. Generally, you are better off using fgets() and sscanf().
  • Print newlines at the end of lines of output - especially in the print loop.
  • Use (your own) standardized error reporting functions similar to err_exit(); that is just a trivial version of what could be a much more complex system of functions, but having such functions available means you are less likely to skimp on error reporting.
  • Use more white space. Use space around most operators. I recommend using a bigger indent than 2 (either 4 or 8).
  • Avoid magic numbers (like 5) if they appear more than once in the code. 0 and 1 are not magic numbers.
  • Use the uintptr_t to print addresses as integers, and the <inttypes.h> header, and the names defined in there such as PRIuPTR. (I usually print addresses in hex, but decimal isn't automatically wrong.) The <inttypes.h> header is from C99; that might cause you problems if your C compiler is retrograde enough not to provide C99 support.
  • Note that this is not the recommended solution for your problem with int type; on a 64-bit machine, it uses vastly more memory than the original solution.
  • However, if you were dealing with an array of separately allocated large structures and you were not sure in advance exactly how many you'd need, then this scheme would be more sensible. (You'd probably not be tied to a fixed array size, though.)
  • There are those who cavil at the cast on the return type from malloc(). I prefer it, in part because I learned C on a machine where the cast was crucial, and in part because the cast is mandatory in C++, and I like my code to work in the C subset of C++ even when I'm writing in C. (The compiler in question was before there was a standard C; it was word-addressed machine; malloc() returned char *, but the bit pattern for a char * was different from the bit pattern for an anything * (e.g. int *) to the same address.)
Jonathan Leffler
A: 

I believe I have found the solution to your predicament. Simply follow these steps:

(1) Shift the statement:

a=(int *)malloc(sizeof(int));

out of the for loop (put it just before the for), & change it to:

a=(int *)malloc(5 * sizeof(int));

(2) Change your scanf statement to:

scanf("%d",&a[i]);

That should do the trick.

Kedar Soparkar