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.
Related
I am trying to compile a C program using MinGW on Windows 7 (64-bit). The code is given below:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
void readRegDwordValue() {
HKEY hKey = HKEY_LOCAL_MACHINE;
char const *subKey = "Software\\Metpl\\My Program";
char const *pValue = "MJP_XXX";
uint32_t flags = RRF_RT_REG_DWORD;
int *pvData = NULL;
int64_t result = RegGetValue(hKey, &subKey, pValue, flags, NULL, pvData, sizeof(DWORD));
if (result != ERROR_SUCCESS) {
printf("Error getting value. Code: ");
printf("%" PRId64 "\n", result);
} else {
printf("Value data: ");
printf("%" PRId32 "\n", *(int32_t*)pvData);
}
}
int main() {
readRegDwordValue();
return 0;
}
I get the following warning:
gcc -O3 -Wall -c -o readReg.o readReg.c
readReg.c: In function 'readRegDwordValue':
readReg.c:13:22: warning: implicit declaration of function 'RegGetValue'; did you mean 'RegSetValue'? [-Wimplicit-function-declaration]
13 | int64_t result = RegGetValue(hKey, &subKey, pValue, flags, NULL, pvData, sizeof(DWORD));
| ^~~~~~~~~~~
| RegSetValue
I have included windows.h which includes winreg.h that contains the definition of the RegGetvalue function. Why is the compiler not able to find it? Also, since it is suggesting that I meant RegSetValue, does it mean it is able to find this one? !!
The linker gives the following error:
gcc readReg.o -o readReg.exe -L -liphlpapi -ladvapi32
d:/__sdk/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: readReg.o:readReg.c:(.text+0x45):
undefined reference to `RegGetValue'
collect2.exe: error: ld returned 1 exit status
What am I missing here? I have been pulling my hair over this for over 8 hours now and not able to understand where I am making the mistake. I have not been able to find much relevant discussion online on this either.
Desperately request some input on this so that I can move forward. Thanks in advance.
Finally! All the hair-pulling bore fruit. And, all the peripheral learning along the journey now seems exhilarating. Following is what works with MinGW-w64 (32-bit):
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <inttypes.h>
char buffer[1024]; // Based on need. This is the max that I need.
DWORD bufferSize = sizeof(buffer);
DWORD readRegDwordValue(HKEY hKey, char const *subKey, char const *pValue) {
long unsigned int *p = NULL;
int64_t result = RegGetValue(hKey, subKey, pValue, RRF_RT_REG_DWORD, p, &buffer, &bufferSize);
if (result != ERROR_SUCCESS) {
return 4294967295; // max unsigned int.
}
return ((DWORD *)buffer)[0]; // return the first element of the buffer.
}
char * readStringValue(HKEY hKey, char const *subKey, char const *pValue) {
long unsigned int *p = NULL;
int64_t result = RegGetValue(hKey, subKey, pValue, RRF_RT_REG_SZ, p, &buffer, &bufferSize);
if (result != ERROR_SUCCESS) {
return "Error";
}
return (char *)buffer;
}
int main() {
char *string = readStringValue(HKEY_LOCAL_MACHINE, "Software\\Metpl\\My Program", "companyName");
printf("string:%s%s%d%s \n", string, " (length = ", strlen(string), ")");
DWORD integerValue = readRegDwordValue(HKEY_LOCAL_MACHINE, "Software\\Metpl\\My Program", "sampleInteger");
printf("integer:(%lu%s\n", integerValue, ")");
return 0;
}
I have tested this code and it gives correct results. Since I only need to get the correct result or an error, I have not added additional error-checking in the code.
Thanks, #CGio3, for pointing me to MinGW-w64. I have made many Portable C programs and a few Windows programs with the version I have and got too comfortable with it, I guess. Anyway, lesson learnt.
Hope this helps someone who has been struggling with the subject.
I've been learning C for like 5 days, and so I tried doing some little projects.
I created a very simple library that automates getting a string from the user,then implemented it in a program which just outputs the string's value.
It runs perfectly on Windows (Compiled through MSVC: 'cl .\main.c /link .\get_string\m_string.obj') but it doesn't in Linux (Compiled with gcc using : 'gcc -o test main.c m_string.o')
I know that MAX being 1024 makes absolutely no sense, it's just a test value.
//main.c
#include <stdio.h>
#include "get_string/m_string.h"
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}
// m_string.h
#include <stdio.h>
#define MAX 1024
char *get_string(char *prompt);
//m_string.c
#include "m_string.h"
char *get_string(char *prompt)
{
char *s[MAX];
printf("%s", prompt);
fgets(s, MAX, stdin);
return s;
}
Running main.c on Windows works as expected:
Something: something
something
Running main.c on Linux:
Something: something
(null)$
Since I am using a very big value for the maximum memory used in fgets(), I don't think that a buffer overflow is the cause (Would have probably gotten Segmentation Fault otherwise).
Thank you for reading and I hope someone can shed some light on the matter for an absolute beginer like me.
char *s[MAX]; creates an array of MAX pointers, not char values.
ALWAYS enable your compiler's warnings. It would have found this. With gcc, I use -Wall -Wextra -pedantic.
get_string returns a pointer to a variable that no longer exists once get_string returns.
One way to solve this is to allocate a buffer using malloc, and free that buffer in the caller.
#include <stdio.h>
#include <stdlib.h>
#define MAX 1024
char *get_string( const char *prompt ) {
char *s = malloc( MAX );
if ( !s )
return NULL;
printf( "%s", prompt );
if ( !fgets( s, MAX, stdin ) ) {
free( s );
return NULL;
}
return s;
}
int main( void ) {
char *inputf = get_string( "Something: " );
if ( !inputf ) {
perror( NULL );
exit( 1 );
}
printf( "%s", inputf );
free( inputf );
return 0;
}
Demo on Compiler Explorer
It really does not run "correctly", because this is undefined behavior. You may not access temporary storage outside of the scope in which it was defined.
In addition to this, you also have a type error: char *s[MAX]; defines an array of MAX char pointers. Using this as a string buffer should not have been allowed past the compiler.
If you do not want to allocate memory dynamically for this, then make the string buffer static. You can even make it thread-local (since C11) if for some reason you plan to use this function in concurrent environments.
#include <stdio.h>
#define MAX 1024
char *get_string(const char *prompt)
{
static _Thread_local char s[MAX];
printf("%s", prompt);
if (!fgets(s, MAX, stdin)) {
s[0] = '\0';
}
return s;
}
int main(int argc, char *argv[])
{
char *inputf = get_string("Something: ");
printf("%s", inputf);
return 0;
}
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 should compile my program with spec flags to gcc. Then gcc complained about return values not taken care of. WhenI use variables to take the return values then gcc complains again:
$ gcc -pedantic -Wall -ansi -O4 miniShell.c
miniShell.c: In function ‘cd’:
miniShell.c:108:9: warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
^
miniShell.c:107:12: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
char * return_value;
^
How can I resolve the warnings? My program is as follows.
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_LEN 1024
#define BUFFERSIZE 1024
int mystrcmp(char const *, char const *);
void err_syserr(char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int main() {
char line[BUFFER_LEN];
char* argv[100];
char* path= "/bin/";
char progpath[20];
int argc;
size_t length;
char *token;
int i=0;
int pid;
while(1) {
i = 0;
printf("miniShell>> ");
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
length = strlen(line);
if (line[length - 1] == '\n') {
line[length - 1] = '\0';
}
if(strcmp(line, "exit")==0) {
break;
}
token = strtok(line," ");
while(token!=NULL) {
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL;
argc=i;
for(i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
strcpy(progpath, path);
strcat(progpath, argv[0]);
for(i=0; i<strlen(progpath); i++) {
if(progpath[i]=='\n') {
progpath[i]='\0';
}
}
pid= fork();
if(pid==0) {
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
} else {
wait(NULL);
printf("Child exited\n");
}
}
return (0);
}
int mystrcmp(char const *p, char const *q)
{
int i = 0;
for(i = 0; q[i]; i++)
{
if(p[i] != q[i])
return -1;
}
return 0;
}
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Reading between the lines, I guess the original problem you were trying to solve was a warning along the lines of:
warning: ignoring return value of ‘chdir’
And you've tried to fix that by assigning the return value to a variable (which itself is now unused).
getcwd and chdir can both return error codes if they fail, which are the return values GCC is warning you about. If you want to fix the warning properly you should add logic to your code to detect and handle these error cases. Otherwise, you are potentially continuing with a state inconsistent with your assumptions (for example, you may be in an unexpected directory if getcwd failed and left your buffer in an incorrectly initialised state).
I had thought that this could be over-ridden by casting the result of the function call to void, but this does not work (you can still play tricks, but they get messy!). The GCC documentation for the warn_unused_result attribute says:
The warn_unused_result attribute causes a warning to be emitted if a
caller of the function with this attribute does not use its return
value. This is useful for functions where not checking the result is
either a security problem or always a bug,
Which suggests that you don't want to find a workaround for the warning, and should really be checking the return value for error conditions.
If you really want to do it, assign the result to a variable as you have done, then add a single use of that variable, cast to void:
int res = chdir (cwd);
/* I promise I don't need to check this return value. */
(void) res;
The other users have answered how you can get rid of the warning by fixing your code, but just for reference: If you want to 'ignore' the warnings, compile with the flag:
-Wno-unused-but-set-variable
The compiler usually gives you a tag at the end of a warning (in your case, it's -Wunused-but-set-variable). To ignore it, just change the -W to a -Wno-
Hope this helps!
There are actually 2 things wrong here in your code. The first one probably caused you to change your code, which then caused the warning you are now asking about.
I bet you the first initial warning was about chdir. As the documents say:
man chdir(3): "Upon successful completion, 0 shall be returned.
Otherwise, -1 shall be returned, the current working
directory shall remain unchanged, and errno shall be set to
indicate the error."
As it says, chdir can return an error code stating if anything went wrong and the first initial warning was caused due to the fact you simply ignored that value.
Then you changed your code and assigned the value to another variable and got:
warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
and you can see in this function that you are only setting a value to that variable but don't actually use it later which means you can delete it:
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Same thing for return_value. You can simply delete them both since they are not in use.
In case you want to avoid the first initial warnings you can always do something like this:
int res = chdir (cwd);
(void) res;
This is an assurance made by you to the compiler that everything is fine and he can ignore the warning.
I'm currently coding for a challenge question in a book I'm reading. My code executes perfectly with the correct output, but i"m getting a warning in my code and I'm just wondering why.
I'm getting a warning on the line that reads:
int countdownStart = atoi(numInput);
The warning I'm getting says:
Implicit declaration of function 'atoi' is invalid in C99
#import <readline/readline.h>
#import <stdio.h>
int main(int argc, const char * argv[]){
printf("Who is cool? ");
const char *name = readline(NULL);
printf("%s is cool!\n\n", name);
printf("What should I start counting? ");
const char *numInput = readline(NULL);
int countdownStart = atoi(numInput);
for (int i = countdownStart; i >= 0; i--){
if (i % 3 == 0){
printf("%d\n", i);
if (i % 5 == 0){
printf("Found one!\n");
}
}
}
return 0;
}
You have to include stdlib.h
#include <stdlib.h>
Next time you encounter similar warnings just run man atoi and the manual pages should state that which header file should be included.