0

I have a function that gets an integer as a parameter. I want to send a char array's address to it, then print the array from its address. I mean:

void printSomeThing(int x){
    printf("Variable is: %s\n", /*What to type here?*/);
    //I want this printf to write "file.txt"
}

....

int main(){
    char filename[10] = "file.txt";
    char *filePointer = filename;  //So it points to filename[0]'s address.
    int x = /*How to convert the address of the pointer (or the char array) to an integer?*/
    printSomeThing(x);
}

So, I want to send the char array's address to the function and print that address's value.

NOTE: I can't change the printSomeThing parameter. It has to be an int.

Mohammad Kholghi
  • 533
  • 2
  • 7
  • 21
  • 4
    You can try casting your pointer to an `int` and then back to `char *`, but it may not work (undefined behavior). On many systems this is impossible, e.g. 64-bit systems where a pointer is 64 bits but `int` is only 32 bits. The code will compile but most likely crash when you run it. – Nate Eldredge Dec 16 '20 at 04:58
  • 5
    Why do you need to do this? What's the actual problem you're trying to solve? The way to pass a pointer value to a function is to use an argument of pointer type. – Keith Thompson Dec 16 '20 at 05:02
  • 1
    The first thing to do is add `printf("%zu %zu\n", sizeof(filePointer), sizeof(x));` to your code. If it prints two different numbers, then you simply cannot do what you're hoping for. – user3386109 Dec 16 '20 at 05:03
  • 1
    @NateEldredge is right. The proper way to do this is to cast your pointer to a `uintptr_t` which was made available in C99 (someone correct me if I'm wrong). Other than, casting pointers to integers normally leads to Bad Things happening. – Daniel Walker Dec 16 '20 at 05:10
  • 1
    https://stackoverflow.com/questions/15602280/convert-pointer-to-int-and-back-to-typed-object – Support Ukraine Dec 16 '20 at 05:42
  • 1
    https://stackoverflow.com/questions/22624737/casting-a-pointer-to-an-int/22624888 – Support Ukraine Dec 16 '20 at 05:45
  • @KeithThompson I want to send the memory address to the function so that I can get its value. – Mohammad Kholghi Dec 20 '20 at 08:31
  • Yes, obviously that's what you want to do. But if the function needs an address to be passed as an argument, why doesn't the function define its parameter with a pointer type? (There are some rare cases where defining a function with an integer argument that then treats that argument as an address value makes sense. You haven't said anything that indicates why you'd need to do that.) – Keith Thompson Dec 20 '20 at 23:06
  • Because the function gets an integer and is a general-purpose function. Other functions also pass integers to it. Thank you. @KeithThompson – Mohammad Kholghi Dec 21 '20 at 03:51
  • 1
    But *why* does it take an integer argument? How does it know whether to treat its argument as an integer or as a pointer? The specification in your question makes what you're trying to do pretty much impossible: an `int` often cannot hold a pointer value. On many systems, `int` is 32 bits and pointers are 64 bits. The obvious solution is to have one function that takes an integer and another that takes a pointer. Why exactly would that not meet your requirements? I think you have an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Keith Thompson Dec 21 '20 at 05:44

3 Answers3

1

The proper way to convert between pointer addresses and integers is to use the uintptr_t integer type. This is a type guaranteed to be large enough to hold an address (unlike int). This code is fairly safe and portable:

#include <stdio.h>

void printSomeThing(uintptr_t x){
    printf("Variable is: %s\n", (char*)x);
}

int main(){
    char filename[10] = "file.txt";
    char *filePointer = filename;  //So it points to filename[0]'s address.
    uintptr_t x = (uintptr_t)filePointer;
    printSomeThing(x);
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
1

If sizeof(int) != sizeof(char*), then what you're trying to do is not possible, in general.

However, there is a way to still make this work. Before I tell you how to achieve this, let me reiterate what others have said: you should not use an int as a pointer. This is not a good idea. What I am going to demonstrate is just that: a demonstration. Just because it can be done doesn't mean it should be done.

One way to make this work is to map memory at an address smaller than 1 << (sizeof(int) * 8). Then, copy the string you want to that memory location. Now, you can pass this pointer to your printSomething(int) function.

There is one problem with this solution: it's not portable, so it doesn't always work. I couldn't get it to work with clang on macOS, but it does work here. Here is the code I used.

#include <stdio.h>
#include <sys/mman.h>
#include <string.h>

void printSomething(int x){
    printf("Variable is: %s\n", (char*) x);
}

int main(){
    char filename[10] = "file.txt";
    char *allocd = mmap((void*) 0x10000, sizeof(filename)+1,
                        PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    strcpy(allocd, filename);
    printSomething((int) allocd);
}

Another solution that should probably only be used as a demonstration is one where you ask gcc to define a section at a low memory address. This answer does something along those lines. This is probably not portable either.

Sagar
  • 1,617
  • 9
  • 17
0

The best way I could think to do this given that you dont want to just pass a pointer to the array - would be to cast it to an unsigned long in order to give it to the function.

However your compiler might complain that you are passing an integer value to a string pattern in printf but that is by virtue of the design you are using.

If you dont need to use printSomeThing(int i) then just pass the char* itself or use a void* if you need other things passed through and use some sort of flag to tell the function what type you passed

Emily-TTG
  • 531
  • 3
  • 18