2016-09-13 1 views
0

В моей ниже коде я получаю следующие предупреждения пошли постройки:Почему в этом коде работает указатель, а не нормальная переменная?

В функции «on_btn_Convert_clicked»: |

предупреждение: назначение делает целое число от указателя без приведения [включен по умолчанию] |

предупреждение: передающий аргумент 2 из 'gtk_label_set_text' делает указатель из целое число без актера [включено по умолчанию] |

|| === Сборка завершена: 0 ошибок, 2 предупреждения (ов), 1 секунд (ы)) === |

Если я запустил программу, так как она откроет графический интерфейс, но данная кнопка вызовет ошибку сегментации при нажатии и сбое программы.

#include <stdlib.h> 
#include <stdio.h> 
//include gtk headers 
#include <gtk/gtk.h> 

//define pointer variable names 
GtkWidget *plblFileName; 
GtkWidget *pbtnConvert; 
GtkWidget *pbtnFileChooser; 


//prototype functions 
char on_btn_Convert_clicked(); 

char on_btn_Convert_clicked() 
{ 
    //define variables 
    char hello; 

    hello = "hello!"; 

    gtk_label_set_text(GTK_LABEL(plblFileName), hello); 
    return 0; 
} 

//start main loop 
int main(int argc, 
     char **argv) 
{ 
    GtkBuilder *builder; 
    GtkWidget *window; 
    GError  *error = NULL; 

    //Init GTK+ 
    gtk_init(&argc, &argv); 

    //Create new GtkBuilder object 
    builder = gtk_builder_new(); 
    //Load UI from file. If error occurs, report it and quit application. 
    //Replace "tut.glade" with your saved project. 
    if(! gtk_builder_add_from_file(builder, "testGTK.ui", &error)) 
    { 
     g_warning("%s", error->message); 
     g_free(error); 
     return(1); 
    } 

    //Get main window pointer from UI 
    window = GTK_WIDGET(gtk_builder_get_object(builder, "windowMain")); 

    // get pointer to the label and button 
    plblFileName = GTK_WIDGET(gtk_builder_get_object(builder, "lbl_FileName")); 
    pbtnConvert = GTK_WIDGET(gtk_builder_get_object(builder, "btn_Convert")); 
    pbtnFileChooser = GTK_WIDGET(gtk_builder_get_object(builder, "btn_Choose")); 

    //connect the button with its signal 
    g_signal_connect(G_OBJECT(pbtnConvert), "clicked", G_CALLBACK(on_btn_Convert_clicked), NULL); 

    //Destroy builder, since we don't need it anymore 
    g_object_unref(G_OBJECT(builder)); 

    //Show window. All other widgets are automatically shown by GtkBuilder 
    gtk_widget_show(window); 

    //Start main loop 
    gtk_main(); 

    return(0); 
} 

Однако, если я сделаю переменную «hello» указателем, тогда ошибки исчезнут, и все будет работать.

Как это:

char on_btn_Convert_clicked() 
{ 
    //define variables 
    char *hello; 

    hello = "hello!"; 

    gtk_label_set_text(GTK_LABEL(plblFileName), hello); 
    return 0; 
} 

Я не понимаю, как указатель, объект, который просто указывает на место в памяти, может быть равна «привет» и по-прежнему работать, как это?

Может ли кто-нибудь объяснить мне, почему переменная 'char hello' должна быть указателем (*) и не может быть просто строкой или символом char?

И наконец, можете ли вы обобщить, почему это работает против версии с нормальной переменной char?

+0

Использование '=' с указателем означает, что указатель указывает на ячейку памяти, указанную другим операндом –

ответ

3

Константа строка символов, как на самом деле "hello" массив из шести символов ('h', 'e', 'l', 'l', 'o' и терминатором '\0'). Когда вы его используете, он может распадаться на указатель на свой первый элемент.

Это как реальный массив:

char hello_array[6] = { 'h', 'e', 'l', 'l', 'o', '\0' }; 

, а затем назначить его к указателю, как

char *hello = &hello_array[0]; 

выше, является то, что в основном то, что происходит, когда вы делаете

char *hello = "hello"; 

Когда у вас есть

char hello = "hello"; 

это как делать

char hello = &hello_array[0]; 

Это просто не работает. То же самое при вызове функции он ожидает аргумент типа char *, и вы передаете аргумент типа char. Эти два типа не являются одинаковыми на протяжении длительного периода.


Еще один способ объяснить это может означать, что вы думаете что-то вроде этого: переменная - это место для хранения значения. Когда у вас есть переменная типа char, вы можете сохранить один символ. Когда у вас есть указатель на символ, вы можете точно указать это, указатель на символ (на самом деле адрес памяти).

Например, предположим, что мы имеем

char a = 'a'; 
char *b = &a; 

Несколько графически его можно было видеть, как это:

 
       +-----+ 
The variable a: | 'a' | 
       +-----+ 
       ^
       | 
       +-----------------------+ 
The variable b: | Address of variable a | 
       +-----------------------+ 

переменная bточек переменной a.

Разница должна быть совершенно очевидна, если вы печатаете размеры двух типов:

printf("sizeof(char) = %zu\n", sizeof(char)); 
printf("sizeof(char *) = %zu\n", sizeof(char *)); 

Первая строка должна сказать, что размер char является 1 (это указано в спецификации C, чтобы всегда быть 1 Кстати). Размер указателя должен быть либо 4 (в 32-разрядной системе), либо 8 (в 64-битной системе).

+0

, благодарю вас за то, что вы это четко изложили. –

5

Потому что в первой части кода

char hello; 
hello = "hello!"; 

это не так, как компилятор уже предупреждал вас.

string literal в виде "Hello!" возвращает указатель на первый элемент, то есть, адрес первого элемента в строке, и которые не могут быть сохранены в char. Вам понадобится char *, чтобы это удержать.

Кроме того, вы можете использовать массив char hello[] = "hello!";. Это создает массив и инициализирует массив строковым литералом «привет!», Который также должен работать нормально, но простой (скалярный) char не будет работать.

1

У вас есть хороший ответ от @SouravGhosh, вот предложение:

Не используйте Глобалы как plblFileName:

char on_btn_Convert_clicked() 
{ 
    //define variables 
    char *hello; 

    hello = "hello!"; 

    gtk_label_set_text(GTK_LABEL(plblFileName), hello); 
    return 0; 
} 

Вместо этого используйте правильный прототип для этого сигнала ("clicked")

void on_btn_Convert_clicked(GtkButton *button, gpointer user_data) 
{ 
    //define variables 
    char *hello; 

    hello = "hello!"; 

    gtk_label_set_text(GTK_LABEL(user_data), hello); 
} 

и подключите сигнал, пропущенный на этикетке:

g_signal_connect(G_OBJECT(pbtnConvert), "clicked", 
       G_CALLBACK(on_btn_Convert_clicked), plblFileName); 
Смежные вопросы