Home > other >  Can not print out the elements of an array in a for-loop
Can not print out the elements of an array in a for-loop

Time:02-11

Why can not I print out the elements of an array in a for-loop? My environment is Windows 7 Maximum, gcc (MinGW.org GCC-6.3.0-1) 6.3.0 I input the data from the prompt like 3 1 2 3. I can do, e.g., printf("%" PRId64 " ", marray[2]) but from the for-loop it doesn't work.

Here is the source code:

#define __USE_MINGW_ANSI_STDIO 1
#define __STDC_FORMAT_MACROS 1

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

size_t read_size() {
    size_t x;
    scanf("%lu", &x);
    return x;
}

int64_t read_int64() {
    int64_t x;    
    scanf("%" SCNd64, &x);
    return x;
}

int main() {
    size_t *size;
    *size = read_size();
    int64_t *marray = malloc(sizeof(int64_t) * *size);
    for (size_t i = 0; i < *size; i  ) {
        marray[i] = read_int64();
    }
        
    for (size_t i = 0; i < *size; i  ) {
        printf("%" PRId64 " ", marray[i]);
    }
    free(marray);
    return 0;
}

CodePudding user response:

First, in main() you have:

size_t *size;  //creating an uninitialized pointer

then you call

*size = read_size();  
^ (dereferencing an uninitialized pointer

which will result in undefined behavior. (read about nasal demons here. Essentially anything can happen here. On my system, it was a run-time error. ( ...Local 'size' was referenced before being initialized. ) Note: If you do not see something similar, turn on your compiler warnings.

So, as pointed out in comments, using a pointer here is not the right approach anyway...

*size = read_size();

Suggest changing the following:

size_t read_size(){
    size_t x;
    scanf("%lu", &x);
    return x;
}

To:

size_t read_size(void){//note, its portable to include `void` in `void` prototypes
    size_t x;
    scanf("%zu", &x); //zu, not lu for size_t format specifier
    return x;
}

Then call it like this:

//size_t* size;
size_t size = read_size();

Then also change these :

int64_t* marray = malloc(sizeof(int64_t)**size);
...
for (size_t i = 0; i < *size; i  ){

to:

int64_t* marray = malloc(sizeof(int64_t) * size);
if(marray)
{//always verify successful call before attempting to use memory
...
for (size_t i = 0; i < size; i  ){//removed the dereference on size  

EDIT - comments indicate need to create 2D array dynamically:

comments indicate that your intention is that

int64_t* marray = malloc(sizeof(int64_t)**size);

creates a two dimension array. That statement will only create a single dimension array, and likely not of the size that you think.

In general, create a pointer to the array, then create pointers to the each column... (for example, without knowing both dimensions, the following will create both to be size)

int rows = size
int cols = size
int64_t **marray = malloc(sizeof(int64_t) * rows*cols);
if(!marray)//handle error
{
      for(int i = 0; i < cols ; i  )
      {
           marray[i] = malloc( rows * sizeof(int64_t));
           if(!marray[i]) //handle error;
      }
}

This method approximates the method indicated in comments, however IMO this is not the best way. It creates non-contiguous blocks of memory for each call to malloc, and requires one call to free() for each call to malloc(). A much better approach is here. (Uses only one call to malloc()/free() to create and free a 2D array.)

  • Related