Get array index from pointer difference in c or c++ - c++

I know how to get a pointer from a pointer and adding a index. But is it possible to get the index of a array if you only have a pointer to the array beginning and a pointer to one element element?
#include <iostream>
#include <array>
auto pointer_from_diff(auto *x, auto *y) -> auto {
return // ? what here?
}
auto main() -> int {
auto x = std::array{1, 2, 3, 4};
auto *p = &x[2];
std::cout << pointer_from_diff(x.data(), p) << std::endl;
}
Because someone seem to not like the question being tagged in c, here is some actual c-code for those of you who does not speek c++.
#include <stdio.h>
int pointer_from_diff(int *x, int *y) {
return ?;// ? what here?
}
int main() {
int x[] = {1, 2, 3, 4};
int *p = &x[2];
int index = pointer_from_diff(x, p);
printf("%d", pointer_from_diff(x, p));
}
Note: I marked this as c++/c, not because I want to use c, but because my guess is that the solution is similar for both languages. A solution in c that is possible to implement in c++ is therefore acceptable.
I also over/missuse auto for the lols in the c++ version and that is unrelated to the question.

&x[k] is the same as &x[0] + k.
Thus, p - &x[0] is &x[0] + 2 - &x[0], which is 2.

Related

Initializing an array of pointers to structs in C++

Initializing an array of pointers to structs in C can be done using compound literals.
typedef struct {
int a;
int b;
} s;
In C:
s *ptrArray[] = {
&(s){
.a = 1,
.b = 2
},
&(s){
.a = 4,
.b = 5
}
};
How can this be done in C++?
I have also seen the difference in initializing structs in C++ not using compound statements:
s s1 = { a: 7, b: 8 };
First - initializing anything to the address of a temporary value seems extremely fishy, in C as well. Are you sure that's valid? Hmmm. Anyway, a C++ compiler will really not let you do that.
As for the your designated (named-field) initialization C++ line - it's actually non-standard, it's a GNU C++ extension, and you can't rely on it.
You could do this:
struct s { int a, b; };
int main() {
s data[] = { { 1, 2 }, { 4, 5 } };
// instead of ptrArray[i], use &(data[i])
}
This compiles just fine. But - a more C++'ish version of this code would be:
#include <array>
struct s { int a, b; };
int main() {
std::array<s, 2> data { s{ 1, 2 }, s{ 4, 5 } };
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
Why would you want to use std::array? Here's one explanation of the benefits. Actually, you could do slightly better and repeat yourself less with:
int main() {
auto data = make_array(s{ 1, 2 }, s{ 4, 5 });
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
The make_array function is taken from here; you also have std::experimental::make_array(), but that's not standardized yet.
If you want to add or remove elements from data at run-time, you might switch to using std::vector:
#include <vector>
struct s { int a, b; };
int main() {
std::vector<s> data { s{ 1, 2 }, s{ 4, 5 } };
// instead of ptrArray[i], use &(data[i]),
// or use iterators, or ranged for loops
}
The reason your initialize was failing is you were attempting to initialize the array of pointers to struct to the address of numeric literal constants. The same as:
#define A 5
int b = &A; /* NOT HAPPENING */
(you can't take the address of 5)
You can solve your problem by simply initializing an array of s instead of an array of pointers to s, e.g.:
s ptrarr[] = { {1, 2}, {4, 5} };
With that change, your array will initialize fine, e.g.
#include <iostream>
typedef struct {
int a;
int b;
} s;
int main (void) {
s ptrarr[] = { {1, 2}, {4, 5} };
int cnt = 0;
for (auto& i : ptrarr)
std::cout << "ptrarr[" << cnt++ << "] : " << i.a << ", " << i.b << "\n";
}
Example Use/Output
$ ./bin/ptrarrystruct
ptrarr[0] : 1, 2
ptrarr[1] : 4, 5

Size of an object without using sizeof in C++

This was an interview question:
Say there is a class having only an int member. You do not know how many bytes the int will occupy. And you cannot view the class implementation (say it's an API). But you can create an object of it. How would you find the size needed for int without using sizeof.
He wouldn't accept using bitset, either.
Can you please suggest the most efficient way to find this out?
The following program demonstrates a valid technique to compute the size of an object.
#include <iostream>
struct Foo
{
int f;
};
int main()
{
// Create an object of the class.
Foo foo;
// Create a pointer to it.
Foo* p1 = &foo;
// Create another pointer, offset by 1 object from p1
// It is legal to compute (p1+1) but it is not legal
// to dereference (p1+1)
Foo* p2 = p1+1;
// Cast both pointers to char*.
char* cp1 = reinterpret_cast<char*>(p1);
char* cp2 = reinterpret_cast<char*>(p2);
// Compute the size of the object.
size_t size = (cp2-cp1);
std::cout << "Size of Foo: " << size << std::endl;
}
Using pointer algebra:
#include <iostream>
class A
{
int a;
};
int main() {
A a1;
A * n1 = &a1;
A * n2 = n1+1;
std::cout << int((char *)n2 - (char *)n1) << std::endl;
return 0;
}
Yet another alternative without using pointers. You can use it if in the next interview they also forbid pointers. Your comment "The interviewer was leading me to think on lines of overflow and underflow" might also be pointing at this method or similar.
#include <iostream>
int main() {
unsigned int x = 0, numOfBits = 0;
for(x--; x; x /= 2) numOfBits++;
std::cout << "number of bits in an int is: " << numOfBits;
return 0;
}
It gets the maximum value of an unsigned int (decrementing zero in unsigned mode) then subsequently divides by 2 until it reaches zero. To get the number of bytes, divide by CHAR_BIT.
Pointer arithmetic can be used without actually creating any objects:
class c {
int member;
};
c *ptr = 0;
++ptr;
int size = reinterpret_cast<int>(ptr);
Alternatively:
int size = reinterpret_cast<int>( static_cast<c*>(0) + 1 );

Use decltype to declare the return type

I've got the following code snippet:
int odd[] = { 1,3,5,7,9 };
int even[] = { 0,2,4,6,8 };
// returns a pointer to an array of five int elements
decltype(odd) *arrPtr(int i) {
return (i % 2) ? &odd : &even; // returns a pointer to the array
}
int main()
{
int *res1 = arrPtr(3);
decltype(odd) *res2 = arrPtr(3);
auto res3 = arrPtr(3);
}
For the first line I get the following error message:
int (*arrPtr(int i))[5]
returns a pointer to an array of five int elements
Error: a value of type "int (*)[5]" cannot be used to initialize an entity of type "int *"
Why can't int* be used to initialize my return value from arrayPtr()? I would have assumed that the compiler is doing an explicit conversion.
Furthermore, what would one use as return type (best practice)?
It seems odd is declared as an array of int:
int odd[5];
The type of odd is int[5] and taking the address (or adding a * to decltype(odd)) of this array yields an int(*)[5]. It seems, you actually want to use the decayed type of odd:
decltype(+odd) arrPtr(int i) {
return i % 2? odd: even;
}
int main() {
int* res1 = arrPtr(3);
decltype(+odd) res2 = arrPtr(3);
auto res3 = arrPtr(3)
}
Note this use of unary + which forces decay of the array to become a pointer to the first element of the array.
If you really mean to return a pointer to the array, you'd need to use a suitable type when capturing the result (assuming the original implementation):
int (*res1)[5] = arrPtr(3);
decltype(odd)* res2 = arrPtr(3);
auto res3 = arrPtr(3);
Note, that this is a pointer to an array of 5 int, i.e., you'd access an element of it using
(*res1)[3];
or
res1[0][3];
int (&)[5] can decay to int *, it is not the case for int (*)[5].
You may change your code to
decltype(odd)& arrPtr(int i) {
return (i % 2) ? odd : even; // returns the reference to the array
}
and then
int main()
{
int *res1 = arrPtr(3);
decltype(odd)& res2 = arrPtr(3); // int (&)[5]
auto res3 = arrPtr(3); // int*
const auto& res4 = arrPtr(3); // const int (&)[5]
}

How to initialize pointer to pointer with premade data?

I have a pointer to a pointer, since I can't pass dynamic arrays to functions. However, if I want to initialize that pointer-to-pointer with premade data, how can I set it since {a,b,c} notation for arrays won't work for pointers?
You can do this:
static int row1[] = {1, 2, 3};
static int row2[] = {4, 5, 6, 7};
static int row3[] = {8, 9, 10, 11, 12, 13};
static int *pptr[] = {row1, row2, row3};
At this point, pptr can be assigned to an int**:
int **p = pptr;
[This answer is only relevant if you need a double*. Your question was edited to say pointer to pointer - if that's what you need, this answer is not relevant.]
You can do this instead:
double fValues[3] = { 1, 2, 3 };
The variable fValues is already a pointer - array variables without the [] are pointers to the first element of the array. This is not a dynamic array, so you don't need to allocate/free its memory.
Assuming your function that takes a double pointer looks something like this:
void Func(double* pDbl) {...}
you'd call it like this:
Func(fValues);
You can create small dynamic arrays recursively something like this:
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct
{
int* pValues;
size_t Count;
} List;
const List ListEnd = { NULL, 0 };
List NewList(int Value, List SubList)
{
List l;
l.Count = SubList.Count + 1;
if (SubList.Count == 0)
{
l.pValues = malloc(sizeof(int));
}
else
{
l.pValues = realloc(SubList.pValues, l.Count * sizeof(int));
}
if (l.pValues == NULL)
{
// do proper error handling here
abort();
}
// moving data isn't necessary if the list elements are
// in the reverse order
memmove(&l.pValues[1], &l.pValues[0], SubList.Count * sizeof(int));
l.pValues[0] = Value;
return l;
}
void PrintDynArr(int* pValues, size_t Count)
{
while (Count--)
{
printf("%d\n", *pValues++);
}
}
int main(void)
{
int* p;
PrintDynArr(p = NewList(1,
NewList(2,
NewList(3,
NewList(4, ListEnd)))).pValues,
4);
free(p);
return 0;
}
Output:
1
2
3
4

How do I do something like this some_function({1,1,1,1})?

Lets say I have a function with prototype like this: int func(int * a), and it accepts an array as an argument.
How do I do this without the compiler showing errors everywhere: func({1,1,1,1})
Like this:
int func(int * a);
void somewhere_else()
{
int arr[4] = { 1, 1, 1, 1 };
func(arr);
}
Don't use raw arrays, and certainly don't pass pointers to them into functions. Ew! We're not in 1975 any more.
#include <cstddef>
#include <iostream>
#include <vector>
void func(std::vector<int> const& v) {
for (std::size_t i = 0; i < v.size(); i++)
std::cout << v[i] << " ";
}
int main() {
func({ 1, 2, 3, 4 });
}
// Output: "1 2 3 4 "
This requires a compiler that is compliant with certain features of C++11. Namely initializer lists.
You can use std::initializer_list:
int func(std::initializer_list<int> a) {
// do something with a here
}
Or you can write a wrapper that uses std::initializer_list (if for some reason you cannot change the original function):
int func_wrapper(std::initializer_list<int> a) {
std::vector<int> b = a;
func(b.data());
}
one way to do that would be
#include <iostream>
#include <stdio.h>
void abc (int *a,int z)
{
int m= z/sizeof(*a);
for(int i=0;i<m;i++)
{
std::cout<<"values " <<*a<<"\n";
a++;
}
}
int main()
{
int ar[]={11,12,13,14,15,1166,17};
std::cout << sizeof(ar)<<"size\n";
abc(ar,sizeof(ar));
getchar();
}
here in this case you dont need to worry about size and all. In case of
int ar[3]={1,2,3} that will give junk values if you try and search for NULL as
the third place is occupied by element 3
All you need is an (int[]) cast:
#include <iostream>
static void f (int* a) {
while (*a) std::cout << *a++ << "\n" ;
}
int main() {
f ((int[]){1,2,3,4,0}) ;
}
This code outputs
1
2
3
4
It works in C too -- see this ideone link.
Updated to add: I posted a new question about the legality of this construct, and Mat's answer is worth reading if you're interested in that kind of thing. Briefly, it seems that it is valid only in C99, but that some compilers allow it as an extension in all C/C++ variants.