Is #define var bad with strcmp? - c

Can i compare#definevarible andchar * in strcmp as below.
#include<stdio.h>
#include<string.h>
#define var "hello"
int main()
{
char *p ="hello";
if(strcmp(p,var)==0)
printf("same\n");
else
printf("not same\n");
return 0;
}
Is there any risk comapre #define with char *as above example?

Don't trust us, trust the preprocessor output
File "foo.c"
#include <stdio.h>
#include <string.h>
#define var "hello"
int main(void)
{
char *buf="hello";
if(strcmp(buf,var)==0) // Is this good
printf("same");
return 0;
}
now:
gcc -E foo.c
lots of output because of standard system libraries then...:
# 5 "foo.c"
int main(void)
{
char *buf="hello";
if(strcmp(buf,"hello")==0)
printf("same");
return 0;
}
as you see your define has been safely replaced by the string literal.
When you have a doubt, just apply this method to make sure (more useful when converting to strings or concatenating tokens, there are traps to avoid)
In your case, you could also avoid the macro and use:
static const char *var = "hello";
which guarantees that only 1 occurrence of "hello" is set (saves data memory).

No, there is no risk to comapre #define with char* at all.
#include <stdio.h>
#include <string.h>
#define var "hello"
int main(void)
{
char *buf="hello";
if(strcmp(buf,var)==0) // Is this good
printf("same");
return 0;
}

Related

How can i pointer char variable add to list char variable in C Programming

i stucked, need to add pointer char value to list char value. pointer char value includes username (windows machine) and list char value includes startup path. I tried to strcat but it breaks the first ";" part.
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *username = getenv("USERNAME");
//printf("%s\n", username);
char shortcutpath[100] = "C:\\Users\\";"\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"; //2 ; is weird, i just tried
strcat(shortcutpath, username);
printf("%s\n",shortcutpath);
return 0;
}
Output = C:\Users%username% ,needs to continue
Need to assign a variable "C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup" this path
Is there any easy way to do that? Or something other usefull things?
You probably want this:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char* username = getenv("USERNAME");
char shortcutpath[100] = "C:\\Users\\";
strcat(shortcutpath, username);
strcat(shortcutpath, "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup");
printf("%s\n", shortcutpath);
return 0;
}
But the more correct way would probably be to get directly the APPDATA environnement variable:
int main(void)
{
char shortcutpath[100];
char* appdata = getenv("APPDATA"); // C:\Users\<yourusername>\AppData\Roaming
strcpy(shortcutpath, appdata);
strcat(shortcutpath, "\\Microsoft\\Windows\\Start Menu\\Programs\\Startup");
...
char shortcutpath[255] = "C:\\Users\\";
strcat(shortcutpath, username);
strcat(shortcutpath, "\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup");

Why using crypt in glibc cause compiler warning?

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.

Declaration char* not working with strcat()

This code compiles without errors, but upon opening the app, it says:
file.exe has stopped working
#include <string.h>
#include <stdio.h>
int main() {
char *a = 'Hello';
char *b = 'World';
strcat(a,b);
puts(a);
}
Where did I go wrong?
You need to allocate sufficient space and use double quote instead of single quote. You could use array.
#include <string.h>
#include <stdio.h>
int main() {
char a[20] = "Hello";
char b[10] = "World";
strcat(a,b);
puts(a);
}
Constant strings are not modifiable. This is a proper way to declare, initialize and modify a string buffer in C:
#include <string.h>
#include <stdio.h>
int main() {
char a[20];
char *b = "World";
strcpy(a,"Hello");
strcat(a,b);
puts(a);
return(0);
}
You can't do strcat on pointer of characters. You only can do strcat on array of characters .... Sorry for my precedent answer, look at the code below :
#include <string.h>
#include <stdio.h>
int main() {
char a [20];
char b[20];
strcpy(a,"Hello");
strcpy(b,"World");
strcat(a,b);
puts(a);
return(0);
}

Array with int and char in C

I need to put 3 strings on an array[3][3].
I tried to do it with pointers, but I only receive a single character.
#include <stdio.h>
int array[3][3]
char thing[5] = "thing";
main()
{
thing = array[0][0];
printf("%s", array[0][0];
}
Try this. With due respect your code absolutely incorrect and need many changes. You need to update your programming skills too.
#include <stdio.h>
#include <string.h>
char array[3][6]={0};
char *thing = "this";
main()
{
strcpy(array[0],thing);
printf("%s\n", array[0]);
}

How to make a copy of a string and return its address, assign that to a pointer and print the new string in C? [duplicate]

This question already has answers here:
Passing address of array as a function parameter
(6 answers)
Closed 9 years ago.
I'm writing a function that gets a string, allocates memory on the heap that's enough to create a copy, creates a copy and returns the address of the beginning of the new copy.
In main I would like to be able to print the new copy and afterwards use free() to free the memory. I think the actual function works although I am not the char pointer has to be static, or does it?
The code in main does not work fine...
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
int make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(sizeof(arr));
int i=0;
for(;i<sizeof str_ptr/sizeof(char);i++)
str_ptr[i]=arr[i];
return (int)str_ptr;
}
OK, so based on the comments. A revised version:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
char *ptr=make_copy(arrr);
printf("%s",ptr);
getchar();
return 0;
}
char* make_copy(char arr[])
{
static char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
int i=0;
for(;i<strlen(arr)+1;i++)
str_ptr[i]=arr[i];
return str_ptr;
}
Or even better:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={"abcdef\0"};
printf("%s",make_copy(arrr));
getchar();
return 0;
}
char* make_copy(char arr[])
{
char *str_ptr;
str_ptr=(char*)malloc(strlen(arr)+1);
return strcpy(str_ptr,arr);
}
You're on the right track, but there are some issues with your code:
Don't use int when you mean char *. That's just wrong.
Don't list characters when defining a string, write char arrr[] = "abcdef";
Don't scale string alloations by sizeof (char); that's always 1 so it's pointless.
Don't re-implement strcpy() to copy a string.
Don't cast the return value of malloc() in C.
Don't make local variables static for no reason.
Don't use sizeof on an array passed to a function; it doesn't work. You must use strlen().
Don't omit including space for the string terminator, you must add 1 to the length of the string.
UPDATE Your third attempt is getting closer. :) Here's how I would write it:
char * make_copy(const char *s)
{
if(s != NULL)
{
const size_t size = strlen(s) + 1;
char *d = malloc(size);
if(d != NULL)
strcpy(d, s);
return d;
}
return NULL;
}
This gracefully handles a NULL argument, and checks that the memory allocation succeeded before using the memory.
First, don't use sizeof to determine the size of your string in make_copy, use strlen.
Second, why are you converting a pointer (char*) to an integer? A char* is already a pointer (a memory address), as you can see if you do printf("address: %x\n", ptr);.
sizeof(arr) will not give the exact size. pass the length of array to the function if you want to compute array size.
When pass the array to function it will decay to pointer, we cannot find the array size using pointer.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strdup(const char *str)
{
char *s = (char*)malloc(strlen(str)+1);
if (s == NULL) return NULL;
return strcpy(s, str);
}
int main()
{
char *s = strdup("hello world");
puts(s);
free(s);
}
Points
~ return char* inside of int.
~ you can free the memory using below line
if(make_copy!=NULL)
free(make_copy)
Below is the modified code.
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
char* make_copy(char arr[]);
int main()
{
char arrr[]={'a','b','c','d','e','f','\0'};
char *ptr;
ptr=make_copy(arrr,sizeof(arrr)/sizeof(char));
printf("%s",ptr);
printf("%p\n %p",ptr,arrr);
getchar();
return 0;
}
char* make_copy(char arr[],int size)
{
char *str_ptr=NULL;
str_ptr=(char*)malloc(size+1);
int i=0;
for(;i<size;i++)
str_ptr[i]=arr[i];
str_ptr[i]=0;
return str_ptr;
}

Resources