Why C Macro gets truncated? - c

I am passing a C Macro to a function which receives it as char *. Without any reason the last character from macro gets truncated. I doubt some memory leak, but could not find where.
#define FROM "/some/local/path/from/"
#define TO "/some/local/path/to/"
....
char file[_D_NAME_MAX + 1] = {'\0'};
....
funMove(file, FROM, TO);
....
....
int funMove(char *file, char *from, char *to) {
//here the to value is one character less (/some/local/path/to) slash got truncated
}

There's nothing wrong with the code you've shown us since the following works fine:
#include <stdio.h>
#include <string.h>
#define _D_NAME_MAX 50
#define FROM "/some/local/path/from/"
#define TO "/some/local/path/to/"
char file[_D_NAME_MAX + 1] = {'\0'};
int funMove(char *file, char *from, char *to) {
printf ("[%s] [%s] [%s]\n", file, from, to);
return 0;
}
int main (void) {
strcpy (file, "fspec");
int x = funMove(file, FROM, TO);
printf ("[%d]\n", x);
return 0;
}
It outputs:
[fspec] [/some/local/path/from/] [/some/local/path/to/]
[0]
as expected, so there must be a problem elsewhere if you're seeing to truncated.

Apologies!! Actually, nothing was wrong with the code and the macro didn't get truncated but got overridden. There was another macro with the same name and content except the slash. So, the macro was got replaced instead of the intended one.
#define TO "/some/local/path/to" //header file 1
#define TO "/some/local/path/to/" //header file 2
I just had the header file 2 in mind and misunderstood that the macro got truncated. Actually, the macro from header file 1 was used instead of file 2 which was the intended one.
Thanks for all your answers and support.

Related

How does #define carries the function name in c?

After working for more than 10 years, today a code caught my eye, I am unable to understand the function name defined inside a function gets printed in the output/log without being passed as an argument in macro or being defined as a global variable. Please help me understanding the internal. Please see the screenshot for the reference.
/*...*/
#include <stdio.h>
#define x printf("%s", f);
int main() {
char *f = "MAIN";
printf("Hello World");
x;
return 0;
}
Output:
Hello WorldMAIN
C preprocessor macros simply do text replacement. They have no semantic awareness of your program.
This:
#include <stdio.h>
#define x printf("%s", f);
int main()
{
char* f = "MAIN";
printf ("Hello World");
x;
return 0;
}
Becomes:
#include <stdio.h>
int main()
{
char* f = "MAIN";
printf ("Hello World");
printf("%s", f);;
return 0;
}
Please note that if there is no f declared when this macro is used, you will see a compiler error. If f is declared, but is not a char *, you should see compiler warnings.
Some preprocessor macro best practices include (but are not limited to) using capitalized names, as x by convention looks like a variable or function name; and being careful about what syntactically significant symbols (in this case ;) you include in your macro text.
Hopefully this example was done for the sake of learning, because it is wholly unnecessary. Preprocessor macros wouldn't exist if they didn't serve a purpose, but beware they can easily obfuscate code.
Preprocessor macros are just text replacements. All #include statements are replaced with the content of the specified files. All occurrences of #define'd symbols are replaced with their specified text. All comments are omitted. Etc...
So, in your example:
/*...*/
#include <stdio.h>
#define x printf("%s", f);
int main() {
char *f = "MAIN";
printf("Hello World");
x;
return 0;
}
The preprocessor replaces all instances of x with the text printf("%s", f); before the processed code is then sent to the compiler. So, this is the code that the compiler actually sees:
// contents of <stdio.h> here...
int main() {
char *f = "MAIN";
printf("Hello World");
printf("%s", f);;
return 0;
}

How to declare the data type for variable arguments?

I'm trying to assign data type to world but unable to figure it out.
#include <stdarg.h>
#include <stdio.h>
#define TRACE(arg) TraceDebug arg ;\
void TraceDebug(const char* format, ...);
void TraceDebug(const char* format, ...)
{
char buffer[256];
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int main(void)
{
int a =55;
TRACE((Hello,a));
return 0;
}
Below is the error statement in detail.
main.c: In function 'main':
main.c:28:12: error: 'Hello' undeclared (first use in this function)
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
main.c:28:12: note: each undeclared identifier is reported only once for each function it appears in
TRACE((Hello,a));
^
main.c:13:32: note: in definition of macro 'TRACE'
#define TRACE(arg) TraceDebug arg ;\
^
Is there anyway possible to declare Hello as a variable, after declaring I need to get the address of the variable.
In simple I want to change the below code into a variadic function arguments
for example #define QU(arg1,arg2) as #define QU(arg1,...) since variadic macro is not supported am using variadic functions.
#define TRACE(arg1) QU arg1
#define QU(arg1,arg2) {static const char arg1; \
printf("%p\n",(void*)&arg1);\
printf("%d\n",arg2);}\
int main(void)
{
int aaa =333;
int bbb =444;
TRACE((Hello,aaa));
TRACE((Hello2,bbb));
return 0;
}
1) (title) How to declare the data type for variable arguments?
2) (1st question) I'm trying to assign data type to world but unable to figure it out.
1) The data type for the variadic argument (represented by the ellipses: ... ) is always the type of the variable preceding the ellipses . For this prototype:
int variadicFunc(int a, const char *b, ...);
^^^^^^^^^^ ^^^
type assumes the type const char *
2) From content of your question only, the answer could be to be use a typedef statement:
typedef char World; // a new type 'World' is created
But there are clarifications in the comments:
if i change the string to variable i can reduce the memory size,... (you)
You want to have a variable argument list to pass variables existing in your program that you want to place on a Trace list for debugging
purposes. (is that close?)... (me)
(is that close?) yes, that's the thing am trying to do... Are you always going to pass the same type to this function? Ahh, type will
be like TRACE(("Hello", a,"world")); (you)
It appears you want to enter a variable number of either string literals, or string variables as function arguments, then for those items to be placed into variables, then the addresses of those variables to be stored in a file, for the purpose of saving space.
The following code illustrates how you can pass a variable number of strings (in different forms) into a function, and have the address and content retained into a struct. From this, you should be able to adapt from what I have done here, to something more useful to your needs. Note, I have reserved the first string argument to be used a file location to store addresses.
#define MAX_LEN 200
typedef struct {
unsigned int addr;
char str[MAX_LEN];
} DATA;
int variadicFunc(int argCount, const char *str, ...);
int main(void)
{
char a[] = {"this is a string"};
char b[] = {"another string"};
char c[] = {"yet another string"};
// count non-variable v1 v2 v3 v4
variadicFunc(4, ".\\storage.txt", a, b, "var string", c);
// ^count of variable argument list
return 0;
}
int variadicFunc(int argCount, const char *str, ...)
{
va_list arg;
int i;
char sAddr[10];
DATA *d = calloc(argCount, sizeof(*d));
va_start(arg, str);
FILE *fp = fopen(str, "w");//using first string as filename to populate
if(fp)
{
for(i=0;i<argCount;i++)
{
// retain addresses and content for each string
strcpy(d[i].str, va_arg(arg, const char *));
d[i].addr = (unsigned int)&d[i].str[i];
sprintf(sAddr, "%X\n", d[i].addr);
fputs(sAddr, fp);
}
fclose(fp);
}
return 0;
}

Strcpy and strcat functions in C

I'm using the C programming language in Visual Studio 2015, and I'm simply trying to prompt the user for three sentences of text that are then combined into one, three sentence paragraph. I just can't get my strcpy and strcat functions to work.
Thoughts??
Thank you so much in advance!
#include <string.h>
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MASTERSIZE 300
int main()
{
char *calcTotalMessage(char[100], char[100], char[100]);
#define MSIZE 100
#define MSIZEE 100
#define MSIZEEE 100
int read;
char message[MSIZE];
char m2[MSIZE];
char m3[MSIZE];
char* totalM;
printf("Enter a sentence:");
scanf_s("%s", &message);
printf("Enter another sentence:");
scanf_s("%s", &m2);
printf("Enter third sentence:");
scanf_s("%s", &m3);
totalM = calcTotalMessage(message, m2, m3);
printf(totalM);
return 0;
}
char *calcTotalMessage(char *m1, char *m2, char *m3)
{
void strcat(char, char);
void strcpy(char, char);
char *totalM = "";
strcpy(*totalM, *m1);
strcat(*totalM, *m2);
strcat(*totalM, *m3);
return totalM;
}
char *totalM = "";
So totalM points at a string literal. Modifying literals is disallowed by the C standard. You won't necessarily get a compile time error, but your program has undefined behavior. It's unlikely to behave properly.
strcpy(*totalM, *m1);
Then you attempt to pass strcpy a char (the type of *totalM and *m1), and not a pointer. That character is converted to some nonsensical pointer value that you attempt to write at. That again results in undefined behavior. You compiler even tried to warn you, but instead of heeding those errors you added declarations for functions that don't exist (strcpy(char, char)).
I suggest you pass the output buffer into calcTotalMessage instead of returning it.
void calcTotalMessage(char const *m1, char const *m2, char const *m3, char *output) {
output[0] = '\0';
strcpy(output, m1);
strcat(output, m2);
strcat(output, m3);
}
To be called like this:
char totalM[MSIZE + MSIZEE + MSIZEEE] = {'\0'};
calcTotalMessage(message, m2, m3, totalM);
A point regarding style. You won't usually see function declarations anywhere but at file scope. So don't get too used to declaring functions inside another function scope.

Macro having structure with parentheses

I just found somewhere a code like :
#include"stdio.h"
typedef struct st
{
int num;
char c;
int abc;
} Str, *pStr;
#define MyStr(Dcn) Str(Dcn)
int main()
{
Str Str1;
MyStr(Dcn);
return 0;
}
Please tell what the #define line means here? As it is not giving any compilation problem. So if I use #define something to a "structure with parentheses" then what happens?
Here Dcn can be anything not with quotes. When I used a number instead it showed compilation error.
This defines an alias for Str. It is equivalent to
int main()
{
Str Str1;
Str(Dcn);
return 0;
}
Which simply declares a variable Dcn of type Str.
It's a function-like macro, it's expanded to the right-hand side with the arguments replaced.
A classical example is this, to compute max of two values:
#define MAX(a, b) ((a) > (b) ? a : b)
You can use it like this:
int hello = 12, there = 47;
int what = MAX(hello, there);
The second line will expand to:
int what = ((12) > (47) ? 12 : 47);
In other words, what will be 47. Note that this macro evaluates its arguments more than once, which can be harmful if there are side-effects.
As of C99, you can also do variadic preprocessor macros.
The code you're showing will expand to:
Str Str1;
Str(Dcn); /* This is the macro-expansion. */

Microchip C18 - Weird code behavior (maybe extended-mode / non-extended-mode related)

I have this weird problem with the Microchip C18 compiler for PIC18F67J60.
I have created a very simple function that should return the index of a Sub-String in a larger String.
I don't know whats wrong, but the behavior seems to be related to wether extended mode is enabled or not.
With Extended-Mode enabled in MPLAB.X I get:
The memcmppgm2ram function returns zero all the time.
With Extended-Mode disabled in MPLAB.X I get:
The value of iterator variable i counts as: 0, 1, 3, 7, 15, 21
I'm thinking some stack issue or something, because this is really weird.
The complete code is shown below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char bigString[] = "this is a big string";
unsigned char findSubStr(char *str, const rom char *subStr, unsigned char n, unsigned char m)
{
unsigned char i;
for (i=0; i < n-m; i++)
{
if(0 == memcmppgm2ram(&str[i], (const far rom void*)subStr, m))
return i;
}
return n; // not found
}
void main(void)
{
char n;
n = findSubStr(bigString, (const rom void*)"big", sizeof(bigString), 3);
}
memcmppgm2ram() expects a pointer to data memory (ram) as its first argument. You are passing a pointer to a string literal, which is located in program memory (rom).
You can use memcmppgm() instead, or copy the other string to ram using memcpypgm2ram() or strcpypgm2ram().
Unfortunately I can't test this, as I don't have access to this compiler at the moment.

Resources