C - Get pointer adress to string - c

I'm trying to re-code the printf function. I'm stuck on the %p flag.
As you know, %p flag prints the address of a pointer. The problem is that I would like to get this address in a character string (char *), in order to print it.
Is there a way to get an address ?
Thank you.

You are probably lost on what is a pointer.
Consider this code: char *foo = "bar";
Here, foo is a pointer. A pointer is just a variable that holds the address of some space in memory. Here foo IS the pointer to the string "bar".
Also, address in memory are not magic, they are themselves a number. So you just need to print the number stored in your variable.
Unrelated, it's not a smart move to post a question about a school project, in your real name, with context. It could allow other students or worse, your administration to find that you did not do your personal projects by yourself.

Related

Why address(&) give random variable with array?

char a[] = {'A'};
printf(This is random value %c", &a[0] );
This program invokes undefined behavior, as %c is not the correct conversion specifier for an address. Use %p, and cast the argument to (void*).
Note: In case the argument is of type char*, casting is optional, but for any other type, the casting is necessary.
You are printing the address incorrectly.
%c is for printing characters. To print an address use %p and cast the pointer argument (i.e. the address) to void-pointer. Like
printf(This is random value %p", (void*)&a[0] );
The C standard does not define what is supposed to happen for your program. So in principal anything may happen and random values could be the result. No one can tell for sure what your code wil do (without having expert level knowledge of the specific system you are using).
However, on most systems your code will take 1 byte from the pointer and print it as-if it was a character. So the (likely) reason for your "random characters" is that the address of the array is different every time you start the program. And that is exactly what many systems do...
They use "Address Space Layout Randomization". This basically means that the address of things in your program (here the array) are randomly determined during program start up. The idea is to make it harder for hackers to exploit your program.
Read more here: https://en.wikipedia.org/wiki/Address_space_layout_randomization

Memory address of strings declared using a char pointer

I read that when you declare strings using a pointer, the pointer contains the memory address of the string literal. Therefore I expected to get the memory address from this code but rather I got some random numbers. Please help me understand why it didn't work.
int main()
{
char *hi = "Greeting!";
printf("%p",hi);
return(0);
}
If the pointer hi contains the memory address of the string literal, then why did it not display the memory address?
It did work. It's just that you can consider the address as being arbitrarily chosen by the C runtime. hi is a pointer set to the address of the capital G in your string. You own all the memory from hi up to and including the nul-terminator at the end of that string.
Also, use const char *hi = "Greeting!"; rather than char *: the memory starting at hi is read-only. Don't try to modify the string: the behaviour on attempting to do that is undefined.
The "random numbers" you got are the Memory addresses. They are not constant, since on each execution of your program, other Memory addresses are used.
A pointer could be represented in several ways. The format string "%p" "writes an implementation defined character sequence defining a pointer" link. In most cases, it's the pointed object's address interpreted as an appropriately sized unsigned integer, which looks like "a bunch of random number".
A user readable pointer representation is generally only useful for debugging. It allows you to compare two different representations (are the pointers the same?) and, in some cases, the relative order and distance between pointers (which pointer comes "first", and how far apart are they?). Interpreting pointers as integers works well in this optic.
It would be helpful to us if you could clarify what output you expected. Perhaps you expected pointers to be zero-based?
Note that, while some compilers might accept your example, it would be wiser to use const char *. Using a char * would allow you to try to modify your string literal, which is undefined behavior.

Differences between printing a pointer with and without & in C99

Consider the following code:
const char* text = "hi";
printf("%s\n",text);
printf("%p\n", &text);
printf("%p\n", text);
From where does every printf takes the value it prints?
What are the differences?
So let's remember that a pointer is a memory address. text is, as I suspect you know, a pointer to the first (or 0th, depending on how you like to think about it) block of a char array. The & is the "address" operator, which returns the memory address (that is, a pointer to...) whatever comes after it. Since the literal pointer value of text is itself some kind of data, it has to be stored somewhere in memory. So &text returns the address of where the value of text is stored. Like this:

C pointer initialization differences

I am new to C and have some questions about the pointer.
Question 1 What`s differences b/w the following two? Which way is better to initialize a pointer and why?
int *p=NULL;
int *p;
#include <stdio.h>
void main()
{
char *s = "hello";
printf("%p\t%p",s);
//printf("%p\t%p",&s) it will give me unpredictable result every time
//printf("%p\t%p",(void *)&s) it will be fine
//Question3: why?
}
Question 2: I try to google what is %p doing. According to my reading, it is supposed to print the pointer. It that mean it print the address of the pointer?
Question 1, these are definitions of pointer p. One initializes the pointer to NULL, another leaves it uninitialized (if it is local variable in a function, and not global variable, global variables get initialized to 0 by default). Initializing with NULL can be good, or it can be bad, because compiler can warn you about use of uninitialized variables and help you find bugs. On the other hand compiler can't detect every possible use of uninitialized variable, so initializing to NULL is pretty much guaranteed to produce segmentation fault if used, which you can then catch and debug with a debugger very easily. Personally I'd go with always initializing when variable defined, with the correct value if possible (if initialization is too complex for single statement, add a helper function to get the value).
Question 2, %p prints the address value passed to printf. So printf("%p", pointer); gets passed value of variable pointer and it prints that, while printf("%p", &pointer); (note the extra & there) gets passed address of the variable pointer, and it prints that. Exact numeric format of %p is implementation defined, it might be printed just as a plain number.
Question 3 is about undefined behavior, because format string has more items than what you actually pass to printf. Short answer is, behavior is undefined, there is no "why". Longer answer is, run the application with machine code debugger and trace the execution in disassembly view to see what actually happens, to see why. Note that results may be different on different runs, and behavior may be different under debugger and running normally, because memory may have different byte values in different runs for various reasons.
1) The first is an initialization (to NULL in this case) the second is only a declaration of p as a pointer to int, no initial value is assigned to p in this case. You should always prefer an initialization to prevent undefined behavior.
2) You should cast to void* when using %p to print out a pointer (beware that you are using it too many times in your format specifier). The memory address to which p points is printed.
1)
int *p = NULL
defines and initializes a pointer 'p' to NULL. This is the correct way to initialize pointers in order to get "Seg Fault" if you forget to assign a valid address to this pointer later.
int *p
Only defines a pointer "p" with an unknown address. If you forget to assign a valid value to this pointer before using it, then some compilers will notify you about this mistakes while some others will not and you may access a non-valid address and get a run time error or undefined behaviour of the program.
2) "%p" is printing the address where the pointer is points. Since the pointer holds an address, then "%p" prints this address.
printf("%p\t%p",s);
So the first "%p" will print the address where the pointer "s" points which is the address which stores the string "hello". However, note that you are using twice "%p" but you providing only one pointer to print its address !!
Most compilers will not scream about this cause it is effect-less; however try to avoid it.
Answer1 :
int *p=NULL;
p is a pointer to a int variable initialized with NULL. Here NULL means pointer p is not pointing to any valid memory location.
int *p;
p is a pointer to a int variable. p in uninitialized. Reading uninitialized variables is Undefined Behavior. (one possibility if try to use is that it will throw a segmentation fault)
Answer2:
It prints content of pointer. I mean base address of string "hello"
The main difference is that in *p = NULL, NULL is a pre-defined and standard 'place' where the pointer points.
Reading from Wikipedia,
The macro NULL is defined as an implementation-defined null pointer constant,
which in C99 can be portably expressed as the integer value 0
converted implicitly or explicitly to the type void*.
This means that the 'memory cell' called p contains the MACRO value of NULL.
If you just write int *p, you are naming the memory cell with the name p but this cell is empty.

Copy String from one pointer to another in same process and between 2 processes

So I was asked these 2 questions in my interview-
1-what if I have a code snippet like this in C what will be the output
char *ptr1=malloc(10);
ptr1="abc";
char *ptr2 = malloc(20);
ptr2="defghi";
strcpy(ptr1,ptr2);
printf("%s",ptr1);
I tried this one on my terminal after getting home and it was giving this error
[1] 7673 bus error ./b.out
I would like to know how to copy the string in such a case from one pointer to another.
2- We have 2 processes A and B
This is the code in process A
char *ptr1=malloc(10);
ptr1="abc";
char *ptr2 = malloc(20);
ptr2="defghi";
strcpy(ptr1,ptr2);
now the address of ptr1 is passed to process B using interprocess communication and the code in process B is as follows (ptr1 is the address from process A)
char *ptr3=malloc(10);
ptr3=ptr1
printf("%s",ptr3);
What would be the output of this? If the ans is garbage value or error then in what way can we make ptr3 point to the string pointed by ptr1.
I would like to know how to copy the string in such a case from one pointer to another.
You can't. Pointers do not contain strings, or their characters. They can, however, point to null-terminated arrays of characters, i.e. strings.
Having that in mind, it is important to understand that here:
char *ptr1=malloc(10);
ptr1="abc";
you allocate block of memory (or try to do), assign its address to variable ptr1, and then immediately overwrite that pointer value with a pointer to the arrary represented by string literal "abc". The original pointer value is lost -- you leak that memory. In particular, the assignment absolutely does not copy the characters of the literal into the allocated space.
Now be aware that attempting to modify any part of a string literal invokes undefined behavior, whether the modification is direct or indirect. This:
strcpy(ptr1,ptr2);
constitutes an attempt to modify string literal "abc" indirectly via pointer ptr1. If the question was "what is the output" then it was a trick question. The program has undefined behavior -- it's output cannot be predicted, at least not from the C code alone.
The IPC case is a different trick question. Pointer values are meaningful only in the context of the process in which the pointer was obtained. If you pass that pointer to a different process via some form of IPC, there is no reason to suppose that it is valid in the receiving process. Even if it happens to be valid, there's no telling what it points to. If you want to send a string to another process then you must send the characters, not the pointer.

Resources