компиляция несовместимого типа указателя в C

Мой код

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

void getData(short int *number, char *string)
{
    printf("\nPlease enter a number greater than zero: ");
    scanf("%hd", number);

    printf("Please enter a character string: ");
    scanf("%s", string);
}

void echoPair(short int *number, char *string)
{
    printf("Number: %hd Character(s): %s\n", *number, string); 
}

int main()
{
    short int *number = 0;
    char string[32] = {0};

    printf("This program will ask you to enter a number greater than zero and \na character string with less than 32 characters \ninput.");

    getData(&number, &string);
    echoPair(&number, &string);
    return(0);
}

Код работает нормально, но я получаю эти предупреждения компилятора

warning: passing argument 1 of ‘getData’ from incompatible pointer type
warning: passing argument 2 of ‘getData’ from incompatible pointer type
warning: passing argument 1 of ‘echoPair’ from incompatible pointer type
warning: passing argument 2 of ‘echoPair’ from incompatible pointer type

Если сделать это

    getData(number, string);
    echoPair(number, string);

Предупреждения исчезают, но программа получает «Ошибка сегментации: 11» после того, как я ввожу первое число в функцию getData.

Кто-нибудь знает, как убрать предупреждения и сохранить работу программы?

Спасибо


person afiser    schedule 30.08.2011    source источник


Ответы (2)


Здесь есть ряд проблем.


Во-первых, строка:

short int *number = 0;

должно быть:

short int number = 0;

Поскольку вы использовали первый, он дал вам нулевой указатель на short. Это не то, что вам нужно, так как первое разыменование этого зверя, вероятно, приведет к сбою вашего кода (или, что еще хуже, не приведет к сбою вашего кода, но вызовет странное поведение).


Во-вторых, вам не нужно передавать адрес строк, они автоматически распадаются на адрес, поэтому измените:

getData (&number, &string);
echoPair (&number, &string);

to:

getData (&number, string);
echoPair (&number, string); // but see last point below.

И, наконец, вам не нужно передавать адрес только для того, чтобы напечатать его, вы можете просто передать значение, поэтому:

echoPair (&number, &string);

становится:

echoPair (number, string);

В целом, я думаю, что вы хотите:

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

void getData(short int *number, char *string) {
    printf("\nPlease enter a number greater than zero: ");
    scanf("%hd", number);

    printf("Please enter a character string: ");
    scanf("%s", string);
}

void echoPair(short int number, char *string) {
    printf("Number: %hd Character(s): %s\n", number, string);
}

int main (void) {
    short int number = 0;
    char string[32] = {0};

    printf("Blah blah ...");

    getData(&number, string);
    echoPair(number, string);
    return(0);
}

Кроме того, вы никогда не хотите видеть неограниченное сканирование строк, например:

scanf ("%s", string);

в готовом для производства коде. Это уязвимость переполнения буфера, ожидающая своего появления, поскольку вы не контролируете, что вводит пользователь. В вашем конкретном случае пользователь, вводящий более (около) 30 символов, может вызвать всевозможные странные действия.

Функция scanf предназначена для сканирования форматированного текста, и не так много вещей более неформатированных, чем пользовательский ввод :-)

Если вам нужна надежная функция пользовательского ввода, см. здесь.

person paxdiablo    schedule 30.08.2011
comment
Спасибо большое, все исправил. Как вы можете сказать, я новичок в программировании, и это будет использоваться только для практики, но спасибо за информацию о возможном переполнении, буду иметь в виду для дальнейшего использования! - person afiser; 02.09.2011

Вы объявляете локальную переменную number как указатель на short int. Затем вы передаете указатель на него getData и echoPair. Итак, вы передаете указатель на указатель неправильного типа. Вероятно, вы хотите объявить число как просто короткое целое, а не указатель.

person Tommy    schedule 30.08.2011