-5

I don't understand why the following code doesn't work:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <math.h>

struct data 

{

    int age;

    char name[20];

};


int main()
{
    struct data element[2];
    for (int j = 0; j < 2; j++)
    {
        element[j] = (struct data) malloc(sizeof(struct data));
        printf("Enter fav number%d? \n", j);
        scanf("d", &element[j].age);
        printf("Enter fav word? \n");
        scanf("s", &element[j].name);
    }
    printf("\nThis is what you entered:\n");
    for (int k = 0; k < 2; k++)
    {
        printf("%d. Fav number: %d\n", k, &element[k].age);
        printf("%d. Fav word: %s\n", k, &element[k].name);
    }
    return 0;
}

The compiler error says:

beispiele.c: In function ‘main’:

beispiele.c:199:51: error: conversion to non-scalar type requested

   element[j] = (struct data) malloc(sizeof(struct data));

                                                   ^
beispiele.c:201:3: error: too many arguments for format [-Werror=format-extra-args]

   scanf("d", &element[j].age);

   ^
beispiele.c:203:3: error: too many arguments for format [-Werror=format-extra-args]

   scanf("s", &element[j].name);

   ^
beispiele.c:208:3: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Werror=format=]

   printf("%d. Fav number: %d\n", k, &element[k].age);

   ^
beispiele.c:209:3: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[20]’ [-Werror=format=]

   printf("%d. Fav word: %s\n", k, &element[k].name);

   ^

cc1: all warnings being treated as errors
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
steve178
  • 1
  • 2
  • `scanf` uses `%d` and `%s` to read integer and strings respectively. Also you don't have to pass `&string_variable` as parameter. You have to pass `string_variable` since that itself is a pointer – SureshS Aug 25 '15 at 10:51
  • `element[i]` is a structure in automatic storage and it has therefore already memory allocated. Judging from the code, you don't want `malloc` here, just the two elements that are already there. – M Oehm Aug 25 '15 at 10:52
  • Please activate warnings, which should tell you which of the ´printf` and `scanf` arguments don't match the format specifiers. – M Oehm Aug 25 '15 at 10:53
  • @MOehm Warnings are actually activated as per "_cc1: all warnings being treated as errors_" – Spikatrix Aug 25 '15 at 10:54
  • @CoolGuy: Yep, and the warnings are there. Sorry for that, was judging from the code only. – M Oehm Aug 25 '15 at 10:57
  • "I don't understand why the following code doesn't work:" - oh.. So let me get this straight... You type some garbage and expect that it will do what you imagined it will do? – Karoly Horvath Aug 25 '15 at 10:57

6 Answers6

4

element[j] is not a pointer and is a member of the array so already it has memory allocated statically.

If you need to allocate memory then have array of pointers.

struct data *element[2];
Gopi
  • 19,784
  • 4
  • 24
  • 36
3

There is no need for using malloc (the array allocates all the memory).

Note, using printf does not require the address of the variable, so the & must be omitted before the variable. You do with scanf, as you must pass the address of the variable to which you want to write so that it can be modified (note the %d and %s in the scanf too). However, with the char[20], you do not need the & as the array is a pointer to the begin of the sequence of 20 characters.

int main()
{
    struct data element[2];
    for (int j = 0; j < 2; j++)
    {
        printf("Enter fav number%d? \n", j);
        scanf("%d", &element[j].age);
        printf("Enter fav word? \n");
        scanf("%s", element[j].name);
    }
    printf("\nThis is what you entered:\n");
    for (int k = 0; k < 2; k++)
    {
        printf("%d. Fav number: %d\n", k, element[k].age);
        printf("%d. Fav word: %s\n", k, element[k].name);
    }
    return 0;
}
Joe
  • 380
  • 2
  • 6
1

You have several problems:

  1. Format specifiers start with a % sign. So change

    scanf("d", &element[j].age);
    

    to

    scanf("%d", &element[j].age);
    

    and

    scanf("s", &element[j].name);
    

    to

    scanf("%s", element[j].name);
    

    Wondering why I removed the & from the above scanf? It is because array names gets converted to a pointer to its first element.

  2. These

    printf("%d. Fav number: %d\n", k, &element[k].age);
    printf("%d. Fav word: %s\n", k, &element[k].name);
    

    should be

    printf("%d. Fav number: %d\n", k, element[k].age);
    printf("%d. Fav word: %s\n", k, element[k].name);
    

    because the %d in the printf expects the value(int) and not the address of the variable(int*). Similarly, %s expects a char*, not a char(*)[20]

  3. The cast here is completely wrong and should be removed:

    element[j] = (struct data) malloc(sizeof(struct data));
    

    This is done because malloc returns void* which can be assigned to any pointer type without casting.

      1. etc See other answers.
Spikatrix
  • 20,225
  • 7
  • 37
  • 83
1

You're getting 3 types of errors:

  1. beispiele.c:199:51: error: conversion to non-scalar type requested
    element[j] = (struct data) malloc(sizeof(struct data));

    Check the documentation for malloc - it returns a void pointer to the allocated memory, which you then try to cast to a struct. The struct is obviously not a pointer type, hence the error message.

    To be precise, the error message tells you that you're trying to cast to a type that is not scalar (roughly and incorrectly speaking, that is not a "basic" language type). C-style cast is very permissive and would happily perform many casts, for example, a long long * to a long long, without even a warning.

    Keep in mind that you should not cast the pointer you get from malloc.

    Also, as others have pointed out, this statement:

    struct data element[2];

    declares and automatically allocates the element variable. By calling malloc, you're asking the compiler to allocate it again, dynamically. If you're confused about memory allocation, take a look here.

  2. beispiele.c:201:3: error: too many arguments for format [-Werror=format-extra-args]
    scanf("d", &element[j].age);

    Format strings used by scanf and printf use format specifiers starting with the % symbol, which is missing in all your calls. In this specific call, your format string "d" contains 0 format specifiers, so scanf expects 0 variable addresses to store values in. But you provide 1 address, so the compiler complains for "too many arguments".

    Also, note that scanf needs a the address of a variable because arguments are passed by value - if it took the variable itself instead, it couldn't store the data to be accessible after the scanf call returned. By contrast, printf does not need to modify variables, so it takes variables rather than their addresses.

  3. ^ beispiele.c:208:3: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Werror=format=]
    printf("%d. Fav number: %d\n", k, &element[k].age);

    This error message is pretty self-explanatory. Refer to the previous point about printf's arguments.

Community
  • 1
  • 1
mcmlxxxvi
  • 1,358
  • 1
  • 11
  • 21
0

malloc returns a pointer to the allocated data, not the actual data. You should not cast the result of malloc.

Fix the code accordingly:

 struct data* element[2];
 ...
 element[j] = malloc(sizeof(struct data));
 ...
 free(element[j]);
Lundin
  • 195,001
  • 40
  • 254
  • 396
0

malloc returns a pointer to allocated memory, but you cast the pointer to a struct data. This is what the compiler complains about

error: conversion to non-scalar type requested

Furthermore, you don't need to allocate memory at all, because you already did so by

struct data element[2];

So, when you drop the malloc line, this error should be gone.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198