For example, if I have char character = a, how would I be able to print out it's name, which is "character", along with it's output within a single printf?
I know I can do printf("character = %c", character);, but how can I still print out the input's name if I enter char something = b and make it print out "something = b" instead of "character = b"?
I agree that this sounds like an "XY Problem". Nevertheless, it IS possible with C macros:
https://www.geeksforgeeks.org/how-to-print-a-variable-name-in-c/
#include <stdio.h>
#define getName(var) #var
int main()
{
int myVar;
printf("%s", getName(myVar));
return 0;
}
The printf() output of this example would be "myVar"
You can read more about the "Stringizing Operator" here:
https://www.includehelp.com/c/stringize-operator-in-c.aspx
I think paulsm4's coding example from https://www.geeksforgeeks.org/how-to-print-a-variable-name-in-c/ demonstrates a method of doing this but I thought I might delve into why it is not possible to do this without pre-processor macros. The reason for this is once you compile your C program into assembly language, all variable names are completely done away with. Thus, variables are not stored in RAM or on the disk as names with values associated to them but rather addresses with values associated with them. Because of this, it is impossible once a program is compiled to find out what any of the variables were originally called, and this is one of the reasons why reverse engineering a program from assembly language is so difficult.
Consider this code:
#include<stdio.h>
int main(void) {
int exampleVar = 16;
printf("The memory address of a is: %p\n", (void*) &exampleVar);
// Note the "&" symbol makes this return the
// address of exampleVar rather than its actual value
return 0;
}
If you run this on your computer you will notice it returns a very large hexadecimal number which is its address in RAM. If you were to ask the computer to fetch the value of "exampleVar" it would not use its name but rather the location we just printed and this process would simply return 16, the value of our variable. You'll also notice if you run it multiple times this number changes every time. This is because when you run any computer program the variables are initialized and stored in RAM. Data in RAM tends to constantly be changing and because of this the variables are almost always in a different place every time, though the location will not (typically) change while running the actual program, only between sessions.
If you were to look at the compiled version of this program you would never find "exampleVar" being referred to by its name but rather its address, because for all intents and purposes its address is its name to the computer.
We can store variable name in a string using sprintf() in C.
# include <stdio.h>
# define getName(var, str) sprintf(str, "%s", #var)
int main()
{
int myVar;
char str[20];
getName(myVar, str);
printf("%s", str);
return 0;
}
Output:
myVar
I think the simplest form of what you are asking for (using a macro) is as follows:
#include <stdio.h>
#define print_variable(var) printf("%s = %d\n",#var,var)
int main()
{
int myVar = 42;
print_variable(myVar);
exit(0)l
}
Output:
myVar = 42
This utilized the stringizing operator ('#'), which only works in a macro, as it is a preprocessor operator. As pointed out by others here, this MUST be done at the preprocessor level, because once the program is compiled, all name information is lost.
Related
As part of our training in the Academy of Programming Languages, we also learned C. During the test, we encountered the question of what the program output would be:
#include <stdio.h>
#include <string.h>
int main(){
char str[] = "hmmmm..";
const char * const ptr1[] = {"to be","or not to be","that is the question"};
char *ptr2 = "that is the qusetion";
(&ptr2)[3] = str;
strcpy(str,"(Hamlet)");
for (int i = 0; i < sizeof(ptr1)/sizeof(*ptr1); ++i){
printf("%s ", ptr1[i]);
}
printf("\n");
return 0;
}
Later, after examining the answers, it became clear that the cell (& ptr2)[3] was identical to the memory cell in &ptr1[2], so the output of the program is: to be or not to be (Hamlet)
My question is, is it possible to know, only by written code in the notebook, without checking any compiler, that a certain pointer (or all variables in general) follow or precede other variables in memory?
Note, I do not mean array variables, so all the elements in the array must be in sequence.
In this statement:
(&ptr2)[3] = str;
ptr2 was defined with char *ptr2 inside main. With this definition, the compiler is responsible for providing storage for ptr2. The compiler is allowed to use whatever storage it wants for this—it could be before ptr1, it could be after ptr1, it could be close, it could be far away.
Then &ptr2 takes the address of ptr2. This is allowed, but we do not know where that address will be in relation to ptr1 or anything else, because the compiler is allowed to use whatever storage it wants.
Since ptr2 is a char *, &ptr2 is a pointer to char *, also known as char **.
Then (&ptr2)[3] attempts to refer to element 3 of an array of char * that is at &ptr2. But there is no array there in C’s model of computation. There is just one char * there. When you try to refer to element of 3 of an array when there is no element 3 of an array, the behavior is not defined by the C standard.
Thus, this code is a bad example. It appears the test author misunderstood C, and this code does not illustrate what was intended.
char *ptr2 = some initializer;
(&ptr2)[3] = str;
When you evaluate &ptr2, you obtain the address of memory where is stored the pointer that points to that initializer.
When you do (&ptr2)[3]=something you try to write 3*sizeof(void*) locations further from the location of ptr2, the address of a string. This is invalid and almost sure it finishes with segmentation fault.
No, it's not possible and no such assumptions can be made.
By writing outside a variable's space, this code invokes undefined behavior, it's basically "illegal" and anything can happen when you run it. The C language specification says nothing about variables being allocated on a stack in some particular order that you can exploit, it does however say that accessing random memory is undefined behavior.
Basically this code is pretty horrible and should never be used, even less so in a teaching environment. It makes me sad, how people mis-understand C and still teach it to others. :/
A program usually is loaded in memory with this structure:
Stack, Mmap'ed files, Heap, BSS (uninitialized static variables), Data segment (Initialized static variables) and Text (Compiled code)
You can learn more here:
https://manybutfinite.com/post/anatomy-of-a-program-in-memory/
Depending on how you declare the variable it will go to one of the places said before.
The compiler will arrange the BSS and Data segment variables as he wishes on compilation time so usually no chance. Neither heap vars (the OS will get the memory block that fits better the space allocated)
In the stack (which is a LIFO structure) the variables are put one over eachother so if you have:
int a = 5;
int b = 10;
You can say that a and b will be placed one following the other. So, in this case you can tell.
There is another exception and that is if the variable is an structure or an array, they are always placed like i said before, each one following the last.
In your code ptr1 is an array of arrays of chars so it will follow the exception i said.
In fact, do the following exercise:
#include <stdio.h>
#include <string.h>
int main(){
const char * const ptr1[] = {"to be","or not to be","that is the question"};
for (int i = 0; i < 3; i++) {
for (int j = 0; j < strlen(ptr1[i]); j++)
printf("%p -> %c\n", &ptr1[i][j], ptr1[i][j]);
printf("\n");
}
}
and you will see the memory address and its content!
Have a nice day.
I want to ask how C the variables are stored in C?
To be more clear consider the following code:
int main() {
int a = 1, b;
b = a + 2;
return 0;
}
For example here in what memory C stores the names of variable places.
eg if &a=0x12A7(suppose) &b=0x123B1, then how and where does c stores the variable names like in which memory name a is stored?
Variable names need not be stored at all! The compiler can get rid of them entirely. Imagine, if the compiler is quite clever, it can reduce your entire program to this:
int main(){
return 0;
}
Note that the effect of this program is exactly the same as your original, and now there are no variables at all! No need to name them now, is there?
Even if the variables in your code were actually used, their names are purely a convenient notation when you write the program, but aren't needed by the processor when it executes your code. As far as a microprocessor is concerned, a function like this:
int foo(int x, int y) {
int z = x + y;
return z * 2;
}
Might result in compiled code that does this, in some hypothetical simple instruction set architecture (ISA):
ADD # consumes top two values on stack (x and y), pushes result (z)
PUSH 2 # pushes 2 on stack
MULT # consumes top two values on stack (z and 2), pushes result
RET
The longer story is that variable names are sometimes stored for debugging purposes. For example if you're using GCC you can pass the -g option to emit a "symbol table" which contains things like variable names for debugging. But it isn't needed simply to run a program, and it isn't covered by the language standard--it's an implementation feature which differs by platform.
C doesn't store name of the variables. Its the compiler that stores the names of variables in compiler's symbol table.
This data structure is created and maintained by compiler.
An example of a symbol table for the snippet
// Declare an external function
extern double bar(double x);
// Define a public function
double foo(int count)
{
double sum = 0.0;
// Sum all the values bar(1) to bar(count)
for (int i = 1; i <= count; i++)
sum += bar((double) i);
return sum;
}
may contain at least the following symbol:
Ok first off if you are just getting your head on strait with C this is where to start:
http://condor.cc.ku.edu/~grobe/intro-to-C.shtml
But that is more practical than your question. To answer that we first ask why variables have addresses. The why here is the stack. For a program to operate return calls must be directed to the appropriate buffer so the the pieces all fit together as designed. Now to what I believe was the original question, that is how the actual address is decided, for the answer to that you would have to understand how the processor is implementing the heap.
https://en.wikipedia.org/wiki/Memory_management
"Since the precise location of the allocation is not known in advance, the memory is accessed indirectly, usually through a pointer reference. The specific algorithm used to organize the memory area and allocate and deallocate chunks is interlinked with the kernel..."
Which brings us back to the practical side of things with the abstraction to pointers:
https://en.wikipedia.org/wiki/C_dynamic_memory_allocation
Hope tis gives you a little clearer picture of what's under the hood : )
Happy codding.
I want to know if there is a way to get the size of c function in memory at runtime.
I've used this code but it's not working:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
int main(void)
{
int t[10];
char c;
offsetof(t, p);
p:
return 0;
}
The answer is generally no. You can't. One reason is because functions are not necessarily contiguous in memory. So they don't have a "size". Sometimes, compilers (namely ICC) will make jumps out of the function to a remote part of the binary and jump back in.
See a related question here:
how to find function boundaries in binary code
You are confusing data with code, the variable t is not related to the function main in terms of memory address. t is stored on the stack, main is in the code section.
As for getting the size of the function, there is no standard way to get the size. If you're willing to write a disassembler and static code analysis you might get a rough idea of the size, but even that is not trivial as the final ret instruction may not be the last instruction of the function, say you return from inside a loop.
You could analyse the compiler / linker output data (PDBs, map files, etc).
But then, why do you need to know?
You can examine a disassembly. Disassemblers are available for most environments, and often the compiler itself can generate them from the source for you.
I have seen it done, but I can't really imagine why you would need it. The thing to remember is if you subtract two pointers, it yields a ptrdiff_t, which if added to the first pointer would yield the second. This works for function pointers! So how about this:
#include <stdio.h>
int main (void) {
printf("main is %u bytes long\n", (unsigned) (metamain - main));
return 0;
}
void metamain (void) {
}
Greetings,
I had been studying C++ for a while now.
I'm getting in to pointers now.
But I'm creating a program on C++ that will ask for a string("%s") input.
And I want to display its character on a different line.
But when I run the program I get the wrong letters.
Here's my code;
#include<stdio.h>
#include<stdlib.h>
main() {
char* name;
name = (char *)malloc(sizeof(char));
printf("Enter string: "); scanf("%s", name);
while(*name != '\0') {
printf("%c", name); *name++
}
}
Your reply is highly appreciated.
malloc(sizeof(char)) allocates space for a single character. This is probably not what you want. As the comments below point out, the dereferencing in *name++ is pointless. It does no harm, but perhaps indicates that you're thinking incorrectly about something. name++ has the same effect.
First, if you are going to study C++, you should learn to write C++ programs, not C programs. Here is your program in idiomatic C++:
#include <iostream>
#include <string>
int main(int, char **) {
std::string name;
std::cout << "Enter string: " << std::flush;
std::cin >> name;
std::cout << name << "\n";
}
One advantage of using C++ and its standard libraries over C and its standard libraries is precisely this: you almost never need to use pointers.
But, taking your program for what it is worth, there are sevearal problems. First, in C++, if you want to access the C header files, you should include them with their C++ names:
#include <cstdio>
#include <cstdlib>
Next, main requires a proper signature:
int main(int, char**) {
Most crucially, you are not allocating enough space for your user's name:
name = (char *)malloc(A_BIG_ENOUGH_NUMBER);
Here, you must allocate enough space that scanf() will not write beyond the end of your buffer. But, you can't possibly know how big that is until afte scanf runs. This catch-22 is the source of "buffer-overflow" bugs. For your test program, since you control the input, it is probably OK to just pick a number bigger than any name you'll ever type. In production code, you must NEVER, EVER, used scanf in this way.
name = (char *)mallocc(40);
By the way, if you are compiling this as C code, you should never cast the return from malloc. If you are compiling this as C++ code, you must always cast the return from malloc.
printf("%c", *name); name++
This line is missing a semicolon. Did you compile this program? In future, please only post code that you have compiled. Please use your computer's cut-and-paste features to post your code, never retype the code by hand.
This line has two other problems. First, you must derefence the name pointer to access the data to which it points. (So, *name instead of name.) Second, you need not dereference name in the second statement on this line, since you do nothing with the resulting pointed-to data. (So, name++ instead of *name++.)
Finally, and most importantly, buy, read, and learn from a good book.
Your program is likely printing junk because you only allocate one byte to your string buffer. When the user enters a string, you will have undefined behavior because the scanf will write past the end of name.
You need to alloc name like this:
char *name = (char *)malloc(MAX_STRING_SIZE, sizeof(char));
Even better to use calloc instead of malloc. Define MAX_STRING_SIZE however you like. A reasonable size depends on the application. In your case, if the users will be entering short strings, then perhaps a reasonable buffer size is 64 bytes, or perhaps 80 or 100.
Also, in your while loop, you can increment and dereference your pointer in one step, like this:
printf("%c", *name++);
If you don't like to be that terse, then you can break them apart, but you don't need to dereference the pointer to increment it.
printf("%c", *name); name++;
That's not C++, it's C.
malloc(sizeof(char)) will allocate storage of one char, I expect you wanted more than that.
Also there is no need to allocate dynamically here. Try:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char name[256];
char *p = name;
printf("Enter string: ");
scanf("%s", name);
while (*p != '\0') {
printf("%c", *p);
p++;
}
return 0;
}
I know that if I am inside some function foo() which is called somewhere from bar() function, then this return address is pushed on stack.
#include <stdio.h>
void foo()
{
unsigned int x;
printf("inside foo %x\n", &x);
}
int main()
{
foo();
printf("in main\n");
return 0;
}
In above code, I will get address of first pushed local variable on stack when foo function is active. How can I access the return address (main called foo) that is pushed somewhere before this variable on stack? Is that location fixed and can be accessed relative to first local variable? How can I modify it?
EDIT: My environment is Ubuntu 9.04 on x86 processor with gcc compiler.
There is a gcc builtin for this: void * __builtin_return_address (unsigned int level)
See http://gcc.gnu.org/onlinedocs/gcc/Return-Address.html
On some architectures, you can find it on the stack relative to the first parameter. On ia32, for example, the parameters are pushed (in opposite order) and then a call is made that will push the return address. Remember that the stack almost always (and on ia32) grows downward. Although technically you need the ABI or calling conventions (sometimes called linkage conventions) for your language and hardware platform, in practice you can usually guess if you know how the procedure call machine op works.
The relationship between the first parameter to a function and the position of the return address on the stack is far more likely to be a reliably fixed value than the relationship between a local and the return address. However, you can certainly print out the address of a local, and of the first parameter, and you will often find the PC right in between.
$ expand < ra.c
#include <stdio.h>
int main(int ac, char **av) {
printf("%p\n", __builtin_return_address(0));
return 0;
}
$ cc -Wall ra.c; ./a.out
0xb7e09775
$
When you declare local variables, they are also on the stack - x, for instance.
If you then declare an int * xptr and initialize it to &x, it will point at x.
Nothing (much) stops you from decrementing that pointer to peek a little before, or incrementing it to look later. Somewhere around there is your return address.
You can probe around the stack like so
// assuming a 32 bit machine here
void digInStack(void) {
int i;
long sneak[1];
// feel free to adjust the search limits
for( i = -32; i <= 32; ++i) {
printf("offset %3d: data 0x%08X\n", i, sneak[i]);
}
}
You can get away with this because C is famous for not be very particular in how you index an array. Here, you declare a dummy array on the stack, and then peek around +/- relative to that.
As Rob Walker pointed out, you definitely need to know your compilers calling convention, to understand the data you are looking at. You might print out the address of a few functions, and look for values that are in a similar range, and intuit where the return address is, relative to the dummy array.
Word of caution - read all you want, but don't modify anything using that array, unless either (a) you are absolutely sure about what part of the stack it is you are modifying, or (b) just want to see an interesting/unpredictable crash mode.
To know where the return address is you need to know what the calling convention is. This will typically be set by the compiler and depends on the platform, but you can force it in platform specific ways, for example using __declspec(stdcall) on windows. An optimizing compiler may also invent its own calling convention for functions that don't have external scope.
Barring the use of compiler built-ins to get the return address you would have to resort to inline assembler to get the value. Other techniques that appear to work in debug would be very vunerable to compiler optimizations messing them up.
Please also note that in general there is no guarantee made by the C language that your return address is on a stack, or indeed anywhere in RAM, at all.
There are processor architectures that store the return address in a register, resorting to RAM only when calls start to nest. There are other architectures where there is a separate stack for return addresses, that is not readable by the CPU. Both of these can still have C compilers implemented for them.
This is why you need to be clearer with your environment.
Try this
//test1.cc
//compile with
//g++ -g test1.cc -o test1
#include <stdio.h>
void
print_function(void *p) {
char cmd[128];
FILE *fp;
snprintf(cmd, sizeof(cmd), "addr2line -e %s -f %p", "test1", p);
fp = popen(cmd, "r");
if (fp) {
char buf[128];
while (fgets(buf, sizeof(buf), fp)) {
printf("%s", buf);
}
}
}
void
f2(void) {
print_function(__builtin_return_address(0));
}
void
f1(void) {
f2();
}
int
main(int argc, char *argv[]) {
f1();
return(0);
}
The output should look like
_Z2f1v
/home/<user>/<dir>/test1.cc:30