I am programming a uC. To interact with the uC I've written an menu. In this menu I want to print some information on a PC in a terminal window (in this case tera term VT).
Therefore I want to print something like this:
dec. duty cycle by x% and x should be replaced by a number defined in a marco. To do this, each menu item contains a description string. This string is passed to the menu item via the 1interlaceMenuFct(...)-function an will be printed to the terminal by the print_text(...)-function. So I wrote:
Header file:
#define X 5
#define _STR(s) #s
#define _XSTR(s) _STR(s)
extern void interlaceMenuFct(menuFct_t *fct, const char *description, const char *symbol, menuItem_t *parent, menuFct_t *prev, void *action, unsigned char cnt);
extern void print_text(const char *text);
in code file:
interlaceMenuFct(&decDC_mf,"dec. duty cycle by "_XSTR(X)"%","-",&io_mi,&incDC_mf,&decrementDutyCycle,0);
Here I use the _XSTR(s)-function to replace the X by the number.
Now my "problem": This works, but I do not understand why.
The function interlaceMenuFct(...) expect a pointer to the string. But in the function call I (think that I) create three strings: dec. ..., 5, %
Does it works because these strings are static and the linker place them in ascending order in the memory or does the compiler concatenate this three strings automatically, because there is nothing else written between the "-tags?
§5.1.1.2 of the C standard describes the various stages of compilation (referred to as "translation" in the document). Specifically, stage six is:
Adjacent string literal tokens are concatenated.
In other words, after macro expansion takes place (which is stage 4), any string literals right next to each other (aka adjacent) are combined into one large string. Thus, the 3 strings "dec. duty cycle by ", "5", and "%" are combined into one large string "dec. duty cycle by 5%".
Then, later on in stage 7, the code is actually compiled into machine code, so it sees the interlaceMenuFct call with only one string in that parameter.
Related
I am trying to achieve that C interprets my string as macro.
Hey, let's suppose there is a defined macro as,
#define ABC 900
If i define;
char* s[] = "ABC" ;
then,
printf("%d",s) ;
Is there any way the compiler understands that "ABC" as macro ABC and passes 900 integer value to printf ?
#include<stdio.h>
#define abc 15
int main(void) {
char a[] = "abc" ;
printf("%d",a);
return 0;
}
When i try the above code, instead of my desired output 15 , i get 6487568 which i guess the integer equivalent of that string.
Edit : those were random values , or address of strings. ( as stated below by others )
No, what you're trying to do is double impossible. You can't access variables by name at runtime (string -> variable) because the compiled machine code knows nothing about the names in your C code, and you can't access macros from the compiler because the compiler knows nothing about macros (they're expanded by the preprocessor before the compiler even sees the code).
In other words, compilation / execution happens in multiple stages:
C source code is preprocessed (which gets rid of directives like #include or #define and expands macros).
The preprocessed token stream is passed to the compiler, which converts it to machine code (a runnable program).
Finally the program runs.
Simplified example:
// original C code
#define FOO 42
...
int x = y + FOO;
After preprocessing:
...
int x = y + 42;
After compilation:
movl %ecx, %eax
addl $42, %eax
There is no trace of FOO in step 2, and the final code knows nothing about x or y.
Variable values such as strings only exist at runtime, in step 3. You can't get back to step 1 from there. If you wanted to access information about macros at runtime, you'd have to keep it explicitly in some sort of data structure, but none of this is automatic.
Macros are simple copy paste and they are pretty limited. A macro will not expand if it's quoted or commented.
One solution would be:
#define ABC "900"
char s[] = ABC;
But no, macros cannot be used for what you're trying to do.
When i try the above code, instead of my desired output 15 , i get 6487568 which i guess the integer equivalent of that string.
It's undefined behavior. Most likely it's the address of the string. If you compile with -Wall you will get a warning for this.
I apologize if my formatting is incorrect as this is my first post, I couldn't find a post on the site that dealt with the same issue I am running into. I'm using plain C on ubuntu 12.04 server. I'm trying to concatenate several strings together into a single string, separated by Ns. The string sizes and space between strings may vary, however. A struct was made to store the positional data as several integers that can be passed to multiple functions:
typedef struct pseuInts {
int pseuStartPos;
int pseuPos;
int posDiff;
int scafStartPos;
} pseuInts;
As well as a string struct:
typedef struct string {
char *str;
int len;
} myString;
Since there are break conditions for the concatenated string multiple nodes of a dynamically linked list were assembled containing an identifier and the concatenated string:
typedef struct entry {
myString title;
myString seq;
struct entry *next;
} entry;
The memset call is as follows:
} else if ((*pseuInts)->pseuPos != (*pseuInts)->scafStartPos) {
(*pseuEntry)->seq.str = realloc ((*pseuEntry)->seq.str, (((*pseuEntry)->seq.len) + (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)))); //realloc the string being extended to account for the Ns
memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len)), 'N', (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos))); //insert the correct number of Ns
(*pseuEntry)->seq.len += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //Update the length of the now extended string
(*pseuInts)->pseuPos += (((*pseuInts)->scafStartPos) - ((*pseuInts)->pseuPos)); //update the position values
}
These are all being dereferenced as this else if decision is in a function being called by a function called from main, but the changes to the pseuEntry struct need to be updated in main so as to be passed to another function for further processing.
I've double checked the numbers being used in pseuInts by inserting some printf commands and they are correct in the positioning of how many Ns need to be added, even as they change between different short strings. However, when the program is run the memset only inserts Ns the first time it's called. IE:
GATTGT and TAATTTGACT are separated by 4 spaces and they become:
GATTGTNNNNTAATTTGACT
The second time it is called on the same concatenated string it doesn't work though. IE:
TAATTTGACT and TCTCC are separated by 6 spaces so the long string should become:
GATTGTNNNNTAATTTGACTNNNNNNTCTCC
but it only shows:
GATTGTNNNNTAATTTGACTTCTCC
I've added printfs to display the concatenated string immediately before and after the memset and the they are identical in output.
Sometimes the insertion is adding extra character spaces, but not initializing them so they print nonsense (as would be expected). IE:
GAATAAANNNNNNNNNNNNNNNNN¬GCTAATG
should be
GAATAAANNNNNNNNNNNNNNNNNGCTAATG
I've switched the memset with a for or a while loop and I get the same result. I used an intermediate char * to realloc and still get the same result. I'm looking for for suggestions as to where I should look to try and detect the error.
If you are okay with considering a completely different approach, I would like to offer this:
I understand your intent to be: Replace existing spaces between two strings with an equal number of "N"s. memset() (and associated memory allocations) is the primary method to perform the concatenations.
The problems you have described with your current concatenation attempts are :
1) garbage embedded in resulting string.
2) writing "N" in some unintended memory locations.
3) "N" not being written in other intended memory locations.
Different approach:
First: verify that the memory allocated to the string being modified is sufficient to contain results
second: verify all strings to be concatenated are \0 terminated before attempting concatenation.
third: use strcat(), and a for(;;) loop to append all "N"s, and eventually, subsequent strings.
eg.
for(i=0;i<numNs;i++)//compute numNs with your existing variables
{
strcat(firstStr, "N");//Note: "N" is already NULL term. , and strcat() also ensures null term.
}
strcat(firstStr, lastStr); //a null terminated concatenation
I know this approach is vastly different from what you were doing, but it does address at least the issues identified from your problem statement. If this makes no sense, please let me know and I will address questions as I am able to. (currently have other projects going on)
Looking at your memset:
memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len))), ...
That's the destination. Shouldn't it be:
(memset (((*pseuEntry)->seq.str + ((*pseuEntry)->seq.len) + ((*pseuEntry)->seq.pseuStartPos))
Otherwise I'm missing the meaninging of pseuInts .
I'm working in a C program and I came across a problem. I have this
#define NUMBER_OF_OPTIONS 5
#define NAME_OPTION1 "Partida Rapida"
#define NAME_OPTION2 "Elige Nivel"
#define NAME_OPTION3 "Ranking"
#define NAME_OPTION4 "Creditos"
#define NAME_OPTION5 "Exit"
for (iterator = 1; iterator <= NUMBER_OF_OPTIONS; iterator++){
menu_options[iterator-1]= NAME_OPTION + iterator
}
I want that "NAME_OPTION + iterator" takes the value of the corresponding #define. For example if the variable "iterator" is equal to one, I want menu_options[iterator-1] to take the value of NAME_OPTION1, which is "Partida Rapida".
How can I get this?
Essentially, you can't. #define macros are handled by the C Preprocessor and do textual substitution wherever that macro appears in the code. The macro NAME_OPTION has not been defined, so the compiler should complain. C does not allow appending numbers onto strings, or especially onto symbols like NAME_OPTION. Use an array of const char*, which you can then refer to with your iterator.
You can't use defines as this, you can do:
const char *menu_options[5] = {
"Partida Rapida",
"Elige Nivel",
"Ranking",
"Creditos",
"Exit"
};
If you use #define macro, you just tell preprocessor to replace every occurence of defined word by something else before the code is compiled into machine code.
In this case NUMBER_OF_OPTIONS will be replaced by 5, but there's no occurence of NAME_OPTION*, so nothing will be replaced and you'll probably get an error while preprocessing.
Piere's solutions shows how to do it, but I highly doubt that there's an iterator over char *array, so you have to iterate over given array using an integer index.
#define MAX 7
#define BUFFER 16
#define MODULO 8
typedef struct {
int x;
} BLAH;
if I have:
checkWindow(BLAH *b) {
int mod;
mod = b.MODULO;
}
Specifically can I access MODULO from the BLAH structure?
I think you misunderstand the meaning of preprocessor definitions. #define-d items only look like variables, but they are not variables in the classical sense of the word: they are text substitutions. They are interpreted by the preprocessor, before the compiler gets to see the text of your program. By the time the preprocessor is done, the text of the program has no references to MAX, BUFFER, or MODULO: their occurrences are substituted with 7, 16, and 8. That is why you cannot access #define-d variables: there are no variables to access.
All #defines will be replaced in plain text by the "values" they define, before compilation. They are not variables, just short-hand syntax to make writing programs easy. None of your #def stuff actually reaches the compiler, its resolved in preprocessor.
Now, if you simply replace MODULO in your example by 8, does the resulting code make sense to you?
If it does make sense, please take a Computer Programming 101 course.
When using C preprocessor one can stringify macro argument like this:
#define TO_STRING(x) "a string with " #x
and so when used, the result is as follows:
TO_STRING(test) will expand to: "a string with test"
Is there any way to do the opposite? Get a string literal as an input argument and produce a C identifier? For example:
TO_IDENTIFIER("some_identifier") would expand to: some_identifier
Thank you for your answers.
EDIT: For those wondering what do I need it for:
I wanted to refer to nodes in a scene graph of my 3D engine by string identifiers but at the same time avoid comparing strings in tight loops. So I figured I'll write a simple tool that will run in pre-build step of compilation and search for predefined string - for example ID("something"). Then for every such token it would calculate CRC32 of the string between the parenthesis and generate a header file with #defines containing those numerical identifiers. For example for the string "something" it would be:
#define __CRC32ID_something 0x09DA31FB
Then, generated header file would be included by each cpp file using ID(x) macros. The ID("something") would of course expand to __CRC32ID_something, so in effect what the compiler would see are simple integer identifiers instead of human friendly strings. Of course now I'll simply settle for ID(something) but I thought that using quotes would make more sense - a programmer who doesn't know how the ID macro works can think that something without quotes is a C identifier when in reality such identifier doesn't exist at all.
No, you can't unstringify something.
//unstringify test
enum fruits{apple,pear};
#define IF_WS_COMPARE_SET_ENUM(x) if(ws.compare(L#x)==0)f_ret=x;
fruits enum_from_string(wstring ws)
{
fruits f_ret;
IF_WS_COMPARE_SET_ENUM(apple)
IF_WS_COMPARE_SET_ENUM(pear)
return f_ret;
}
void main()
{
fruits f;
f=enum_from_string(L"apple");
f=enum_from_string(L"pear");
}
You can create an identifier from a string, this operation is called token-pasting in C :
#define paste(n) x##n
int main(){
int paste(n) = 5;
printf("%d" , x5);
}
output : 5