I have a piece of code when I need to include stdlib.h. When I do not include this header, I have no problems compiling my code, but the moment I include the header, my code refuses to compile. It tells me that it expected an identifier or "(" before numerical constant. I have looked through my code and cannot find any issue, and as stated, the code compiles perfectly without including that header.
I am new to C, so excuse my poor code, I am simply wanting to figure out why it would be giving me this error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int execute(char **args)
{
}
char** parse(void)
{
char command[256];
fgets(command, sizeof(command), stdin);
char delimiter[] = " ";
char * pointer = strtok(command, delimiter);
int tokens = 0;
char ** final_command;
while (pointer != NULL)
{
// final_command = (char**)realloc(final_command,
// (tokens+1)*sizeof(char*));
//printf("%s\n", pointer);
//pointer = strtok(NULL, delimiter);
}
}
int main(int argc, char **argv)
{
int EXIT_SUCCESS = 1;
do
{
printf("MyShell> ");
char ** command = parse();
} while (EXIT_SUCCESS);
return EXIT_SUCCESS;
}
I compile using the command gcc -o MyShell MyShell.c
The exact error I am getting says "error: expected identifier or '(' before numeric constant int EXIT_SUCCESS = 1;"
EXIT_SUCCESS is a standard macro (definition) in C. Do not use it as a variable name.
Like NULL, EXIT_SUCCESS is a macro defined in <stdlib.h>, if you include <stdlib.h> you must not use this identifier for other purposes.
In any case your code does not make much sense because it looks like you've got an infinite loop there in main.
I tried to compiler the following code(minimum example, see the edit for the whole code):
// a.c
#include <stdio.h>
#define _XOPEN_SOURCE
#include <unistd.h>
int main(int argc, char* argv[])
{
puts((const char*) crypt("AAAA", "$6$2222"));
return 0;
}
Using clang-7 -lcrypt a.c and it emitted the following warning:
minimum.c:8:24: warning: implicit declaration of function 'crypt' is invalid in C99 [-Wimplicit-function-declaration]
puts((const char*) crypt("AAAA", "$6$2222"));
^
minimum.c:8:10: warning: cast to 'const char *' from smaller integer type 'int' [-Wint-to-pointer-cast]
puts((const char*) crypt("AAAA", "$6$2222"));
^
2 warnings generated.
But ./a.out did seem to work:
$6$2222$6GKY4KPtBqD9jAhwxIZGDqEShaBaw.pkyJxjvSlKmtygDXKQ2Q62CPY98MPIZbz2h6iMCgLTVEYplzp.naYLz1
I found out that if I remove #include <stdio.h> and puts like this:
// new_a.c
#define _XOPEN_SOURCE
#include <unistd.h>
int main(int argc, char* argv[])
{
crypt("AAAA", "$6$2222");
return 0;
}
Then there is no warnings.
How to fix these warnings without removing #include <stdio.h>?
Edit:
Whole program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define _X_OPEN_SOURCE
#include <unistd.h>
#include <assert.h>
void* Calloc(size_t cnt, size_t size)
{
void *ret = calloc(cnt, size);
assert(ret);
return ret;
}
size_t GetSaltLen(const char *salt)
{
size_t salt_len = strlen(salt);
assert(salt_len > 0);
assert(salt_len <= 16);
return salt_len;
}
char* GetSaltAndVersion(const char version, const char *salt)
{
size_t saltlen = GetSaltLen(salt);
/*
* The format of salt:
* $one_digit_number$up_to_16_character\0
* For more info, check man crypt.
*/
char *ret = (char*) Calloc(1 + 1 + 1 + saltlen + 1, sizeof(char));
char *beg = ret;
*beg++ = '$';
*beg++ = version;
*beg++ = '$';
memcpy((void*) beg, (const void*) salt, saltlen + 1);
return ret;
}
void crypt_and_print(const char *passwd, const char *salt_and_version)
{
char *result = crypt(passwd, salt_and_version);
assert(puts(result) != EOF);
}
int main(int argc, char* argv[])
{
if (argc != 4) {
fprintf(stderr, "argc = %d\n", argc);
return 1;
}
char *salt_and_version = GetSaltAndVersion(argv[2][0], argv[3]);
crypt_and_print(argv[1], salt_and_version);
free(salt_and_version);
return 0;
}
I have tried as #Andrey Akhmetov suggested and put the #define onto the first line, but the warnings did not disappear.
The macro _XOPEN_SOURCE is documented in feature_test_macros(7). In particular, the manpage states:
NOTE: In order to be effective, a feature test macro must be defined before including any header files. This can be done either in the compilation command (cc -DMACRO=value) or by defining the macro within the source code before including any headers.
When you include stdio.h, you indirectly include features.h, which uses the feature test macros as defined at that point. In particular, since _XOPEN_SOURCE and friends aren't defined at that point, crypt.h does not declare crypt.
By the time you define _XOPEN_SOURCE it is too late, since features.h has an include guard preventing it from being included twice.
By swapping the order of the first two lines, the code works without raising this warning on my system:
#define _XOPEN_SOURCE
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
puts((const char*) crypt("AAAA", "$6$2222"));
return 0;
}
Your larger example does not work for a second reason: You wrote _X_OPEN_SOURCE as the name of the macro, while the correct name is _XOPEN_SOURCE.
I'm getting a segmentation error (core dump) when I try to run this. It compiles perfectly but I get the error, and I don't know why. There must be a problem with a file writing because without this works good. Any help would be great. Thanks!
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <crypt.h>
#include <string.h>
int
main(void)
{
FILE *f=fopen("shadow1.txt","w");
if (f=NULL)
{
printf("ERROR");
}
unsigned long seed[2];
char salt[] = "$1$........";
const char *const seedchars =
"./0123456789ABCDEFGHIJKLMNOPQRST"
"UVWXYZabcdefghijklmnopqrstuvwxyz";
char *password;
int i;
/* Generate a (not very) random seed.
You should do it better than this... */
seed[0] = time(NULL);
seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
/* Turn it into printable characters from ‘seedchars’. */
for (i = 0; i < 8; i++)
salt[3+i] = seedchars[(seed[i/5] >> (i%5)*6) & 0x3f];
/* Read in the user’s password and encrypt it. */
password = crypt(getpass("Password:"), salt);
/* Print the results. */
//fprintf(f,"%s $ %s",password);
printf("Success Registration to file !");
fclose(f);
return 0;
}
if (f=NULL)
{
printf("ERROR");
}
was the problem...
void Register(char u,char p) {
you probably want these to be char * because of the fprintf that treats them as strings:
fprintf(f,"%s $ %s",u,p);
and since you pass char *s in:
char *password,*username;
//...
Register(username,password);
This would most likely have been caught by compiler warnings. It is a lot faster to get your answer from the compiler than from here.
If you can't figure out why your program isn't working, you can enable all the warnings you should need with -Wall -Wextra and turn warnings into errors with -Werror.
You are not allocating space to hold username so it will segfault on the scanf.
I need to call a .so shared library in PHP, so I write C code using "dlopen" and "dlsym" to do this, and it works.
sample.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
typedef int (*libfunc) (char *msg, int msglen);
int
sfunc(char *msg, int msglen);
sample.c:
#include "sample.h"
int
sfunc(char *msg, int msglen)
{
void *lib;
libfunc lib_func;
int result;
...
lib = dlopen(THE_LIB_PATH, RTLD_NOW);
lib_func = (libfunc) dlsym(lib, THE_LIB_FUNC);
...
result = lib_func(msg, msglen); // return 0 if success
...
dlclose(lib);
return result;
}
It always return 0.
And then I write a PHP extension as a wrapper, it takes PHP arguments and calls the C code before.
php_sample.c:
...
#include "sample.h"
...
PHP_FUNCTION(s_func)
{
char *msg;
long msglen;
int result;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &msg, &msglen) == FAILURE) {
RETURN_NULL();
}
result = sfunc(msg, (int) msglen);
RETURN_LONG(result);
}
Then I added the extension(compiled to .so) to PHP and test the PHP function:
php -r "echo s_func("somestring");"
The call always failed, just return something not zero.
Why? Is there any difference?
Note: I tested this on one other computer and it works. So is there any problems about environments or something?
So I have a program here, that works perfectly when called with
$ gcc test.c -o test -std=c99
But when called in a makefile:
all: test
test: test.c
gcc test.c -o test -std=c99
it produces some warnings instead and gives a segmentation fault.
terminal output:
gcc -g test.c -o tester -std=c99
test.c: In function ‘test_split’:
test.c:43:2: warning: implicit declaration of function‘strdup[-Wimplicit-function-declaration]
char *str_cpy = strdup(str); // Allow mutation of original string
test.c:43:18: warning: initialization makes pointer from integer without a cast [enabled by default]
char *str_cpy = strdup(str); // Allow mutation of original string
Above error does not appear otherwise and does not produse a segmentation fault.
The code segment that fails is here. string.h is included in header.
The file is just a large file to test other functions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define CNRM "\x1b[0m"
#define CRED "\x1b[31m"
#define CGRN "\x1b[32m"
int stringsum(char *s);
void stringsum2(char *s, int *res);
int distance_between(char *s, char c);
char *string_between(char *s, char c);
char **split(char *s);
static int test_num = 1;
static void logger(int passed, char *s)
{
char *res;
char *color;
if (passed) {
res = "PASS";
color = CGRN;
} else {
res = "FAIL";
color = CRED;
}
printf("[Test %d][%s%s%s] %s\n", test_num++, color, res, CNRM, s);
}
static void test_split(char *str, char **correct)
{
int i, pass = 1;
char buf[512] = { 0 };
char *str_cpy = strdup(str); // Allow mutation of original string
char **res = split(str_cpy);
if (!res || !res[0]) {
pass = 0;
sprintf(buf, "split() returned NULL or an empty array");
goto end;
}
for (i = 0; correct[i]; i++) {
if (!res[i]) {
pass = 0;
sprintf(buf, "split() returned fewer words than expected");
goto end;
}
}
if (res[i]) {
pass = 0;
sprintf(buf, "split() returned more words than expected");
goto end;
}
sprintf(buf, "\n%-16s%-16s\n", "Returned", "Expected");
for (i = 0; res[i]; i++) {
char tmp[256] = { 0 };
sprintf(tmp, "%-16s%-16s\n", res[i], correct[i]);
strcat(buf, tmp);
if (strcmp(res[i], correct[i])) {
pass = 0;
goto end;
}
}
end:
logger(pass, buf);
free(str_cpy);
}
static void test_stringsum(char *input, int expected)
{
int test;
char buf[256] = { 0 };
test = stringsum(input);
sprintf(buf, "Returned: %d, Expected: %d", test, expected);
logger(test == expected, buf);
}
static void test_distance_between(char *str, char c, int expected)
{
int test;
char buf[256] = { 0 };
test = distance_between(str, c);
sprintf(buf, "Returned: %d, Expected: %d", test, expected);
logger(test == expected, buf);
}
static void test_string_between(char *str, char c, const char *expected)
{
char *res_char;
char buf[256] = { 0 };
res_char = string_between(str, c);
snprintf(buf, sizeof(buf), "Returned: %s, Expected: %s", res_char, expected);
if (!res_char && expected) {
logger(0, buf);
} else {
if (!expected)
logger(!res_char, buf);
else
logger(!strcmp(res_char, expected), buf);
free(res_char);
}
}
static void test_stringsum2(char *input, int expected)
{
int res_int;
char buf[256] = { 0 };
stringsum2(input, &res_int);
sprintf(buf, "Returned: %d, Expected: %d", res_int, expected);
logger(res_int == expected, buf);
}
int main(void)
{
printf("Testing stringsum()\n");
test_stringsum("abcd", 10);
test_stringsum("a!", -1);
test_stringsum("aAzZ", 54);
test_stringsum("ababcDcabcddAbcDaBcabcABCddabCddabcabcddABCabcDd", 120);
test_stringsum("", 0);
test_num = 1;
printf("\nTesting distance_between()\n");
test_distance_between("a1234a", 'a', 5);
test_distance_between("a1234", 'a', -1);
test_distance_between("123456a12334a123a", 'a', 6);
test_distance_between("", 'a', -1);
test_num = 1;
printf("\nTesting string_between()\n");
test_string_between("a1234a", 'a', "1234");
test_string_between("a1234", 'a', NULL);
test_string_between("A123adette er svaretaasd2qd3asd12", 'a', "dette er sv");
test_string_between("", 'a', NULL);
test_num = 1;
printf("\nTesting stringsum2()\n");
test_stringsum2("abcd", 10);
test_stringsum2("abcd!", -1);
test_stringsum2("bbbdbbbbbdbbdbbbbbddbbbbbdbbdbbbbdbd", 90);
test_stringsum2("", 0);
test_num = 1;
printf("\nTesting split()\n");
test_split("abcd", (char *[]){ "abcd", NULL });
test_split("Hei du", (char *[]){ "Hei", "du", NULL });
test_split("Dette er mange ord", (char *[]){ "Dette", "er", "mange", "ord", NULL });
return 0;
}
Any ideas?
Edit: Added full code.
strdup() is defined a bunch of standards (SVr4, 4.3BSD, POSIX.1-2001), but not the C standard. If you specify -std=c99, gcc by default disables functions defined in these standards. The warning about "implicit declaration" is because C has (annoying) legacy feature of declaring functions implicitly, if you just call them, with certain rules such as return type int, which in this case doesn't match your assignment to char*. These warnings are something you should always fix.
In this case, with -std=c99, it can be fixed by using feature test macros.
The linked manual page tells in which cases the function declaration will be included, so for example this will build it without problems:
gcc test.c -o test -std=c99 -D_POSIX_C_SOURCE=200809L
or with gcc you can use this, which enables pretty much all the features of the libc.
gcc test.c -o test -std=c99 -D_GNU_SOURCE
You could also add the define in the .c file as normal #define before you include the relevant system headers. It may be better to have it at the same place as the -std=c99 though (ie. command line option), because here it kinda goes together with that.
A more extreme solution would be to switch to -std=gnu99. But think carefully about doing that, because then it is easy to accidentally use language features which aren't standard C. And then you will run into much more porting trouble, than just writing a few functions, if you need to port the software to other C compiler which doesn't have GNU extensions.
If you ask gcc for C99 compliant code, it will do as you asked and forget it ever knew about strdup()- This function is not covered by the C99 standard, but is rather POSIX only, so strdup is nowhere in a header file in C99 mode.
As your code doesn't see the prototype for that reason, and doesn't know strdup () will return a pointer but rather assumes an integer, it might do all sorts of havoc when 32-/64- mixed mode code where (sizeof(int) != sizeof(char*)) is generated.
Simple remedy: Don't try to use strdup in c99 mode.
Why you seem to see the bug when compiling using make and not otherwise, is something we cannot deduct from the information you have provided. I guess for some reason you aren't switching gcc into c99 mode when using the command line.