-4

So I am trying to create a little joke with C and I don´t know what I am doing wrong. I see the Error "error: result of comparison against a string literal is unspecified" and do not know how to fix it, can someone help.

#include<stdio.h>
#include<cs50.h>
int main(void){
    string a = get_string("ENTER YOUR NAME FOR READING\n");
    if (a == "david")
    ;
    {
        printf("...");
    }
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

3 Answers3

2

Your code has three issues:

1.

if (a == "david")

a decays to a pointer to the first element of array a.

"david" is a string literal.

With the if Statement, you attempt to compare the address of the array a by the address of the string literal "david". String comparison dies not work that way in C.

Use strcmp() - header string.h to compare strings.

strcmp() returns 0 if the strings are equal. To make the if condition turn true you need to use ! negation operator.

2.

There is a misplaced ; between the if condition and if body. Remove it.

3.

The use of cs50.h is deprecated. If you are not required to use it explicitly, leave your hands off from it.


#include <stdio.h>
#include <string.h>

int main (void) {
    char a[20];

    printf("ENTER YOUR NAME FOR READING:\n");

    if (!fgets(a, sizeof a, stdin))
    {
         fputs("Failure at input", stderr);
         // further Error routine.
    }

    a[strcspn(a, "\n")] = 0;

    if (!strcmp(a,"david"))
    {
        printf("...");
    }
}
0

You cannot compare two strings in c using a comparison operator. Try using

strcmp(const char* one, const char* two)

That is, in your case use

#include<stdio.h>
#include<cs50.h>
int main(void){
    char[] a = get_string("ENTER YOUR NAME FOR READING\n");
    char[] b = "david";
    if (!strcmp(a,"david"))
    {
        printf("...");
    }
}

Also, Strings in c are not declared as strings. They are declared as char arrays

Sai Prashanth
  • 144
  • 2
  • 11
0

Comparing two char pointers like this char *a, *b; a == b; is accepted by the compiler, but if you are using such a syntax to compare the string values, then you may not get the results you are expecting. Some times it may evaluate to true or sometimes to false. The reason is, the program checks whether a and b are pointing to the same address, and not for if they have the same string value. Consider the program below.

#include <stdio.h>
int main()
{
        char* a = "test";

        char* b;

        if ((b="test") == a)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        printf("%p %p\n", a, b);

        return 0;
}

OUTPUT

Impossible
0x55b6bd52d004 0x55b6bd52d004

As you see from the output, the if block is evaluated to true. The reason is also in the output; a and b are pointing to a similar address. Why?

It comes from the string-pooling, one of the compiler optimization. Even though a and b are initialized at different points in the program, as they are referring to the same string constant, the string constant is initialized only once by the compiler.

Here is the objdump of the executable.

$ objdump -s -j .rodata 

a.out:     file format elf64-x86-64

Contents of section .rodata:
 2000 01000200 74657374 00496d70 6f737369  ....test.Impossi
 2010 626c6500 54686f75 67687420 736f0025  ble.Thought so.%
 2020 70202570 0a00                        p %p..          

test is initialized only once. For a quick check, consider this program's output and its objdump .

#include <stdio.h>
int main()
{
        char* a = "test";

        char* b;

        if ((b="test1") == a)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        printf("%p %p\n", a, b);

        return 0;
}

OUTPUT

Thought so
0x557a96aa9004 0x557a96aa9009

objdump

$ objdump  -s -j .rodata a.out  

a.out:     file format elf64-x86-64

Contents of section .rodata:
 2000 01000200 74657374 00746573 74310049  ....test.test1.I
 2010 6d706f73 7369626c 65005468 6f756768  mpossible.Though
 2020 7420736f 00257020 25700a00           t so.%p %p..

It is evident from the output that a and bare pointing to different locations, and both are having different string values that are initialized by the compiler separately. So, if a and b are having similar string values, does a==b always evaluate to true? Consider the below program.

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

int main()
{
        char* a = malloc(sizeof(char) * 5);
        strcpy(a, "test");

        char* b;

        if ((b="test") == a)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        printf("%p %p\n", a, b);

        return 0;
}

OUTPUT

Thought so
0x5607d9938260 0x5607d91fb004

Even though the a and b are having the same string values, if evaluate to false. Why? The address a is pointing, which is created by malloc() belongs to the heap section of the executable, whereas the address b is pointing belongs to the data section of the executable, and they are indeed different.

So what should we do to compare the string values?

Well, it is straight forward, there are already library functions which can perform this task. You can use them withstring.h. Consider the below code.

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

int main()
{
        char* a = malloc(sizeof(char) * 5);
        strcpy(a, "test");

        char* b = "test";

        char* c;

        if (strcmp((c="test"), a) == 0)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        if (strcmp(b, a) == 0)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        if (strcmp(b, c) == 0)
                printf("Impossible\n");
        else
                printf("Thought so\n"); 

        printf("%p %p %p\n", a, b, c);

        return 0;
}

OUTPUT

Impossible
Impossible
Impossible
0x556debf41260 0x556deac28004 0x556deac28004 

Irrespective of where a, b and c are pointing if they all are having the same string values, then strcmp() returns 0.

m0hithreddy
  • 1,752
  • 1
  • 10
  • 17
  • @Mohith You should add it more in the context of the question and address what `"david"` actually is and why it returns an address. – RobertS supports Monica Cellio May 29 '20 at 18:17
  • @RobertSsupportsMonicaCellio I edited my answer, pls go through it. I hope all are happy now :) – m0hithreddy May 29 '20 at 19:15
  • "*... is accepted by the compiler, but if you are using such a syntax...*" - This suggests that comparing pointers would be a bad use in general, which is definitely not the case. – RobertS supports Monica Cellio May 30 '20 at 07:20
  • "*The address ``a`` is pointing, which is created by ``malloc()`` belongs to the heap section of the executable, whereas the address ``b`` is pointing belongs to the data section of the executable*" - The main difference is the different memory address. It has nothing to do with the heap or the stack itself. Also: You are losing focus. – RobertS supports Monica Cellio May 30 '20 at 07:20
  • I love when someone shows effort like you did but IMHO your answer loses the focus to the questioner´s issue. Your treat the topic if the condition is either evaluated to be `true` or `false` which does not cover the OP´s problem in particular. OP is asking for *why* s/he gets the error and how to solve it. Your answer is drifting away too much from these concerns. – RobertS supports Monica Cellio May 30 '20 at 07:20
  • Also: You changed the question itself too much to fit to your answer. That is not correct. It is not what the OP had asked for. - My advice: If you want to contribute your answer to the community, create this answer for the duplicate question, where it would be way more appropriate. – RobertS supports Monica Cellio May 30 '20 at 07:30
  • @RobertSsupportsMonicaCellio Thank you for all of your suggestions. Since I am new to the community, I am trying to learn how to write a proper answer, and your suggestions definitely helped. – m0hithreddy May 30 '20 at 08:50