deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Just stack them on top of each other. A 2D array is a stack of 1D arrays, a 3D array is a stack of 2D arrays, and a 4D array is a stack of 3D arrays. If you get to a 5D array, you have my sympathy. I've used them before (they were dynamic too), and it's excruciatingly tedious.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

If you're not using Turbo C, you can't use graphics.h. If you're new to game programming I'd recommend writing a few text-based games first, then look for a more modern graphics library. SDL and Allegro are two names that pop up regularly for starting out.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

how to solve

Start by trying something on your own or asking a specific question. We're not here as a free homework writing service.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Barring truly hideous solutions like setjmp and longjmp, or terminating the program entirely with exit() or abort(), you really have no choice but to roll back up the recursive chain. This is one of the down sides of recursion, especially when dealing with things like ad hoc traversal over a binary search tree.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Please provide evidence of having done some work yourself if posting questions from school or work assignments.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

That's a compiler extension for gcc that allows non-constant array sizes, it's not a standard feature.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

A pity that the bump action does not get reset....

We considered updating those particular fields upon deleting the last post of a thread, but at the time decided it was too expensive.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

The Windows API defines a macro called ERROR, which is replacing your use of ERROR with whatever value is defined. It does the same thing with TRUE and FALSE, which is why in the past I was forced to do annoying things like this:

enum boolean { B_FALSE, B_TRUE };

This is precisely the type of problem that namespaces were meant to solve. Sadly, the preprocessor is its own beast, and a beast it can be. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

So if I understand correctly pChar = "Hey"; simply replaces the pointer's address with a new address pointed to the new String object.

Correct.

And since C++ doesn't have a garbage collector, it's considered a memory leak.

It's not a memory leak because you didn't explicitly allocate any memory with, for example, new or malloc(). The memory for string literals is owned and managed by the C++ runtime, and it will release them properly.

While cin modifies the object, which it can't access because it's read-only, right?

Correct.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

It's the difference between modifying the pointer (which you own) and modifying the pointed to object (which you don't own).

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You have a pointer to a string literal. String literals are not modifiable, and very often will be stored in read-only memory, so a crash when you try to write to one is unsurprising.

You can fix the error by owning the memory instead of letting the C++ runtime own it:

char buf[100] = "Hello";
char *pChar = buf;

Or, since the pointer is superfluous in this program, you could just use buf directly and remove pChar.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Post an example program, please.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I haven't get what you trying to say.

I really can't simplify it any further.

why is this thread started ?

Because I'm better at writing snippets than coming up with ideas for snippets that people would like to see and learn from. I suspect I'm not alone in that.

I_m_rude commented: confidence! +0
<M/> commented: :) +8
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Um...what?

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

str[j]=str[i];

That's not meaningful, but it's probably a typo where you clearly meant the right hand side to reference str1. However, that's evidence that very similar names are easy to mix up and result in subtle bugs.

You also neglect to terminate the destination string with a null character. And your code is awful. Even if you're using Turbo C, you don't have to write shit code using TurboC-isms. This will compile and run just peachy on your dinosaur of a compiler:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *safe_gets(char *buf, size_t size)
{
    if (!fgets(buf, size, stdin))
        return NULL;

    buf[strcspn(buf, "\n")] = '\0';

    return buf;
}

int main(void)
{
    char str[20], str1[10], str2[10];
    int i, k = 0;

    printf("Enter string 1: ");
    fflush(stdout);

    if (!safe_gets(str1, sizeof str1)) {
        fprintf(stderr, "Input error\n");
        return EXIT_FAILURE;
    }

    printf("Enter string 2: ");
    fflush(stdout);

    if (!safe_gets(str2, sizeof str2)) {
        fprintf(stderr, "Input error\n");
        return EXIT_FAILURE;
    }

    for (i = 0; str1[i] != '\0'; i++)
        str[k++] = str1[i];

    for (i = 0; str2[i] != '\0'; i++)
        str[k++] = str2[i];

    str[k] = '\0';

    printf("%s\n", str);

    return EXIT_SUCCESS;
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

sigh

This will work and is correct:

#include <stdio.h>

int main(void)
{
    int a = 5, b = 10;
    int temp;

    printf("%d %d\n", a, b);

    temp = a;
    a = b;
    b = temp;

    printf("%d %d\n", a, b);

    return 0;
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

If the pragma (excluding a few standard pragmas starting with C99) is supported by your compiler, it must be documented and it must work as documented. But that same pragma need not be supported by a different compiler.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

So that's mean that this code will work "sometimes" but not "always" ?

It means it might work, or it might not. You've broken the type system and invoked undefined behavior. All bets are off.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

why one should not use XoR or arithmetic operation to swap number???

Because it's inferior to using a temporary variable, and the original reason for avoiding a temporary variable is totally irrelevant unless you're on a severely memory constrained platform. And by "severely", I mean so much that you actually map out your register usage and design algorithms to avoid stack or heap use. Oh, and this also assumes that you're writing your code directly in assembly because C is just too heavy.

Then how to swap numbers without using temparory variable.

http://en.wikipedia.org/wiki/XOR_swap_algorithm

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

With only the given information, I'd favor breaking down the row and building a table in C# rather than trying to transform the rows in the query. It looks like all you're doing is splitting each row into two rows with the first id duplicated and assigning either the 2nd or 3rd id:

using System;
using System.Data;
using System.Data.SqlClient;

public class Program {
    public static void Main() {
        string connectionString = "Data Source=localhost;Initial Catalog=Test;Integrated Security=SSPI;";
        string query = "select * from TestTable";
        var table = new DataTable();

        table.Columns.Add("id", typeof(int));
        table.Columns.Add("id1", typeof(int));
        table.Columns.Add("id2", typeof(int));

        using (var connection = new SqlConnection(connectionString)) {
            connection.Open();

            using (var command = new SqlCommand(query, connection)) {
                using (var reader = command.ExecuteReader()) {
                    int pk_seq = 1;

                    while (reader.Read()) {
                        var row = table.NewRow();

                        row["id"] = pk_seq++;
                        row["id1"] = reader["id1"];
                        row["id2"] = reader["id2"];

                        table.Rows.Add(row);
                        row = table.NewRow();

                        row["id"] = pk_seq++;
                        row["id1"] = reader["id1"];
                        row["id2"] = reader["id3"];

                        table.Rows.Add(row);
                    }
                }
            }
        }

        foreach (DataColumn col in table.Columns)
            Console.Write("{0,-5}", col.ColumnName);

        Console.WriteLine();

        foreach (DataRow row in table.Rows) {
            foreach (var item in row.ItemArray)
                Console.Write("{0,-5}", item);

            Console.WriteLine();
        }
    }
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

And before anyone chimes in with swaps using XOR or arithmetic operators that they think are clever: your solution is bad, and you should feel bad.

WaltP commented: Nice. And correct! +14
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Pragmas are implementation-defined (barring a few standard ones starting with C99). Read your compiler's documentation for supported pragmas and what they do.

However, I'll give you an example of a somewhat common pragma: pragma once.

I_m_rude commented: link is damn good! +2
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Your tree generation algorithm isn't really doing anything because the nodes aren't linked together. Compare and contrast:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct node {
    char *token;
    struct node *left;
    struct node *right;
};

struct node *make_node(const char *token, struct node *left, struct node *right)
{
    struct node *ret = malloc(sizeof *ret);

    if (ret) {
        ret->token = strdup(token); /* Using a non-standard function for brevity */
        ret->left = left;
        ret->right = right;
    }

    return ret;
}

struct node *generate_expression_tree(const char *tokens[], size_t n)
{
    struct node *stack[1024];
    size_t top = 0;
    size_t i;

    for (i = n - 1; i < (size_t)-1; --i) {
        if (isalnum((unsigned char)tokens[i][0]))
            stack[top++] = make_node(tokens[i], NULL, NULL);
        else {
            /* Assuming all binary operators for brevity */
            struct node *lhs = stack[--top];
            struct node *rhs = stack[--top];

            stack[top++] = make_node(tokens[i], lhs, rhs);
        }
    }

    return stack[--top];
}

void display_prefix(struct node *root)
{
    if (!root)
        return;

    printf("%s ", root->token);
    display_prefix(root->left);
    display_prefix(root->right);
}

void display_postfix(struct node *root)
{
    if (!root)
        return;

    display_postfix(root->left);
    display_postfix(root->right);
    printf("%s ", root->token);
}

void display_infix(struct node *root)
{
    if (!root)
        return;

    display_infix(root->left);
    printf("%s ", root->token);
    display_infix(root->right);
}

int main(void)
{
    const char *tokens[] = {"+", "*", "A", "B", "/", "C", "D"};
    struct node *root = generate_expression_tree(tokens, sizeof tokens / sizeof *tokens);

    display_prefix(root); puts("");
    display_postfix(root); puts("");
    display_infix(root); puts("");

    return 0;
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

const doesn't mean that the object is stored in read-only memory, though that's a possibility. All const means is that the compiler will enforce read-only uses of the variable. So you can attempt to subvert the type system by casting away const and it'll probably work, but there's no guarantee.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Let's break it down completely into separate statements:

/*
    *p++ = c;
*/
int *temp = p;
*temp = c;
p = p + 1;

Throughout the entire expression, the value of p before the increment is used. Then after the expression reaches a sequence point (the semicolon in this case), the "temporary" variable is destroyed and p evaluates to the incremented value.

The operators are applied in a somewhat unintuitive way. First the ++ binds to p, so you're incrementing the address stored in p. Next, the * binds to the unincremented address due to how the postfix increment operator works. Finally, the assignment operator is applied on the result of the dereference, so c is assigned to the pointed to object.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

ie its a way of identifying words that is independent of the order in which its letters appear.

Yes, pretty much.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Decepticon's solution may be faster or easier than either of these, but I'm ashamed to admit that I don't understand it.

Here's a quickie example to show what I mean. Please excuse the crappy Java, I'm terribly rusty:

import java.util.*;

class Foo {
    public static void main(String args[])
    {
        String[] dictionary = {
            "za",  "zoo", "a",      "aa", "ab",  "an", 
            "baa", "ban", "banana", "na", "nab", "test"
        };
        String word = "abnana";

        for (int i = 0; i < dictionary.length; i++) {
            TreeMap<Character, Integer> freq = new TreeMap<Character, Integer>();

            for (int j = 0; j < dictionary[i].length(); j++)
                freq.put(dictionary[i].charAt(j), 0);

            for (int j = 0; j < word.length(); j++) {
                if (freq.containsKey(word.charAt(j)))
                    freq.put(word.charAt(j), freq.get(word.charAt(j)) + 1);
            }

            boolean match = true;

            for (int count : freq.values()) {
                if (count <= 0) {
                    match = false;
                    break;
                }
            }

            if (match)
                System.out.println("'" + dictionary[i] + "' was found");
        }
    }
}
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I'm not sure how "yes" could have been misinterpreted for that question. Yes, they are equally fast, assuming optimizations are enabled on a modern compiler.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Are they both equally fast ?
right ? (if optimizations are on and these days compilers are used)

Yes.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

int u[]={}

You need to give your array a size. I'm surprised there wasn't an error from this definition.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Do you really think i am seeding forum with questions ?

I have my suspicions from many years answering beginner questions, but it's totally irrelevant. I'd answer your questions regardless, if only to make sure that there's at least one clueful response. Nothing is more damaging to beginners' progress than being mislead by another beginner. And while we don't discourage beginners from trying to help, it's beneficial to have experienced folks around to offer corrections when needed. ;)

I am astonished when you said that line.

It's not an insult. You strike me as unusually observant and thorough. You catch nuances that aren't commonly caught, and you ask questions in a way that have a hint of greater understanding.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

which temporaray variable you are talking about ?

It's implicit and imaginary. The temporary variable is used to describe the functionality of saving the current value, incrementing the value, then returning the saved value.

amazon has asked question in interview "++i" is fast or i=i+1 ? please tell this thing.

It really depends on what you're allowed to assume from the question. If you're assuming that this is C, and both expressions are their own statement, and optimizations are turned on, both will be equally fast because the ultimate machine code is pretty much guaranteed to be identical.

If it's C++ then operator overloading throws a wrench into your assumptions. If the expressions are part of a larger expression then there are a potentially significant number of differences that could affect performance. Finally, on the off chance that you're using an incredibly naive compiler, turning optimizations off could produce less efficient machine code for i = i + 1 if the instruction set of the processor supports an in-place increment instruction and if ++i uses that instruction.

So my expectation when interviewing with this question would be for the candidate to reply with further questions to establish context.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Can you please tell what is difference between "null pointer", "NULL macro", null string, null character and null pointer constant ?

I'm starting to wonder if you're actually a beginner to C or just seeding the forum with questions. ;)

Anyway, a null pointer is the concept of a pointer that points to nothing in particular, but can be predictably tested. That's as opposed to an uninitialized pointer, which could potentially point to anything and thus can't reliably be checked for validity.

A null pointer constant is the concrete form of an initialization value for a null pointer. It's essentially any integer value that equates to 0, either cast or implicitly converted to pointer context.

The NULL macro is a symbolic constant representing a null pointer constant. In C you'll typically see one of these two definitions:

#define NULL ((void*)0)

or

#define NULL 0

In C++ the former is problematic in light of more stringent type system, so NULL is defined simply as 0. But because C allows an implicit conversion from void* to any other pointer type (except a function pointer), NULL can safely include a cast to void*. However, because many C compilers are also C++ compilers, defining NULL as 0 instead of ((void*)0) appears to more common.

Moving away from pointer context, the null character (sometimes referred to as NUL, though there's no standard macro for it) is a character with the value 0. The escape character is '\0', though you …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Would "\n" be stored inside the same address so that it still functions as a new line or not since I'm using this as a .cgi file connected to an html file and only <br> works? Because I have to save "copy" in a text file.

If it's going into a text file then '\n' will act as a newline. If it's being rendered by a browser, I'm not 100% sure whether the CGI interpreter will convert that to an HTML line break or not. That's something you'd need to test and adjust accordingly. I actually haven't worked with CGI in about 10 years, so the details are fuzzy. ;)

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I dont understand the frequency list.

http://en.wikipedia.org/wiki/Letter_frequencies.

If u could please explain the psuedo code a bit?

You're basically just matching at least one of every letter in a given word using the available tiles that the player currently has. All of the words that meet this requirement are words that the player can make with his or her tiles.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

I think the question is actually "how do I generate permutations?"

"nab" isn't a permutation of "abnana". Permutations can get you closer to a complete solution, but that's not all there is to it.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

char *copy = NULL,addressholder2;
copy = &addressholder2;
*copy = *string; //string is the result of the html form
copy[1] = '\0';
strcat(copy,"test"); //HERE IS THE CODE THAT WORKS

This is terrifying. So you have a pointer to a single character, and then immediately start writing beyond that single character as if it were an array to infinite memory. This code exhibits a profound misunderstanding of how pointers and memory work in C.

Assuming that you haven't done something equally wrong with string, it looks like you can use the length of string as a size for copy because it's pretty much guaranteed to be more than enough:

char *copy = malloc(strlen(string) + 1);

if (copy) {
    /* This may be overly paranoid, but handle an empty string */
    if (string[0] != '\0') {
        copy[0] = string[0];
        copy[1] = '\0';
    }
    else {
        copy[0] = '\0';
    }

    /* Now do all of your stuff */
    strcat(copy, "test");

    ...
}

Also, don't forget to release the memory for copy by calling free() at a suitable location (ie. when you're done using the memory).

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

This is a declaration:

int add(int a, int b);

It specifies that add is a function returning an integer that takes two integer parameters. This is the function signature which tells the compiler the "attributes" and "interpretation" of the symbol add.

This is a definition:

int add(int a, int b)
{
    return a + b;
}

Because a body is provided, the declaration becomes a definition, but it still also functions as a declaration.

Here's a summary of object declarations and definitions at either block or file scope:

int a;        /* This is a (tentative) definition */
int b = 0;    /* This is a definition */
extern int c; /* This is a declaration */

int main(void)
{
    int d;        /* This is a definition */
    int e = 0;    /* This is a definition */
    extern int f; /* This is a declaration */

    return 0;
}

Given your eye for detail I'll recommend that you don't concern yourself with tentative definitions for now (because I'm sure you'd ask about it otherwise), just follow the more sensible concept from C++ that it's a definition unless you specifically make it a declaration with the extern keyword.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

This seems more like a job for a frequency list. You can use a dictionary of characters and counts like so:

for each word in the dictionary
    build a frequency list of each character initialized to 0

    for each character in the letter collection
        if the character exists in the frequency list
            increment the count for that character

    if all counts in the frequency list are greater than 0
        mark the word as a match
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

There's no good answer to this question without a significant amount of context.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

ancient dragon will you please tell me that what is that problem of '\n' with fgets. i am not getting it from your answer. will you please explain it more . isn't scanf appends '\n' to the end ? please clearify me.

Try it and see. You can't always rely on someone else to explain things to you, often a little test program is sufficient to answer your own questions.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Yes, you can do that. But the use of ull in the structure definition needs to specify a pointer:

typedef struct node ull;
struct node
{
      int a;
      ull *p;
}hello;

secondly, what is the difference between declaring a structure and defining a structure.

From the C standard:

A declaration specifies the interpretation and attributes of a set of identifiers. A definition of an identifier is a declaration for that identifier that:

  • for an object, causes storage to be reserved for that object;
  • for a function, includes the function body;
  • for an enumeration constant or typedef name, is the (only) declaration of the identifier.

So according to the C standard, this is a declaration:

struct node;

But so is this:

struct node {
    int data;
    struct node *next;
};

However, this is a definition of head and a declaration of the struct in one statement:

struct node {
    int data;
    struct node *next;
} head;

I prefer the C++ terminology that has struct node; as a declaration but listing out the members specifies a definition of the structure. That's simpler, in my opinion, and more consistent, than having both as declarations.

I_m_rude commented: nice one! +0
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Please tell what? Read the link posted by Ancient Dragon in the first reply. It answers your questions about the preprocessor.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

this statement evaluates from right to left. right ?
so, isn't firstly p++ should be incremented ? because (p++) firstly(if we travel from right to left) and then using that value using "*" operator. I know i am wrong. But I am not getting how i am wrong ?

Excellent question! Nice eye for detail. :) The increment operator does indeed evaluate from right to left, but remember how the post increment operator works: it increments the object's value but evaluates to the value before the increment. So this:

int var = 0;

printf("%d\n", var++);
printf("%d\n", var);

Is functionally equiavalent to this:

int var = 0;
int temp = var;

var = var + 1;

printf("%d\n", temp);
printf("%d\n", var);

secondly, in the expression, only y is incremented ? right ? so what is the use of * over there because i am not assiging it's value or using it value in this only expression.

There's no purpose for dereferencing the pointer because you're not doing anything with the result. If all you're doing in the statement is incrementing y then I'd suggest this instead:

++y;

The pre increment operator is conceptually more efficient because it doesn't need to use a temporary variable. In practice there's really no difference because removing that temporary variable if it's not needed was one of the first optimizations in one of the first C compilers. I'd be shocked if any compiler didn't apply that …

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

You have a pointer, not an array. So you need to point that pointer to an array or dynamically allocate some memory to it before using it. Then, you need only remember to dereference the pointer before indexing it:

#include <stdio.h>
#include <stdlib.h>

void display(int (*p)[10])
{
    for (int i = 0; i < sizeof *p / sizeof **p; i++)
        printf("%-2d", (*p)[i]);
}

int main(void)
{
    int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    int (*p1)[10] = &data;              /* Use an existing array */
    int (*p2)[10] = malloc(sizeof *p2); /* Dynamically allocate */

    /* Initialize the dynamic array */
    for (int i = 0; i < sizeof *p2 / sizeof **p2; i++)
        (*p2)[i] = i + 1;

    /* And use the pointers */
    display(p1);
    putchar('\n');
    display(p2);

    return 0;
}
I_m_rude commented: Excellent!! +2
deceptikon 1,790 Code Sniper Team Colleague Featured Poster

arr evaluates to a pointer, you said and i said, arr is a pointer. What is difference in that ?

Context. arr is an array, but when used in value context it evaluates to a pointer to the first element. Saying "arr is a pointer" implies that it's always a pointer, which is a misleading statement.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Codepad is wrong, probably because it doesn't use appropriate flags for strict compilation as C. AT the very least there should be a warning.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

Now deceptikon, nitin1 asked about the first element of the array and for first element there is no need to type cast,if it would have been necessary the compiler would have thrown definite error.

Try to compile the following code and enjoy the definite error along the lines of "cannot convert 'int (*)[2][2]' to 'int*'":

#include <stdio.h>

int main(void)
{
    int arr[2][2][2];
    int *p = arr;

    printf("%d", *p);

    return 0;
}

You clearly don't know what you're talking about. Since nitin1 gets confused easily, please stop replying with incorrect information. In fact, you should read my replies carefully and do a bit of learning yourself.

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

What happens if I removed the "using" word? Will it affect my program?

It would fail to compile...

deceptikon 1,790 Code Sniper Team Colleague Featured Poster

but deceptikon said that typecast is neccassary in this case, otherwise nature will be undefined.

I said that the typecast is safe, but use of the resulting pointer could potentially be undefined. However, phani1092 is incorrect in saying that the cast isn't necessary because you have to either conform to C's type system or subvert it. If you want to assign a naked 2D array to a pointer to int (as in the original example), you must subvert the type system with a cast. If you want to conform to the type system, you must use the correct destination type:

int arr[2][2][2] = {1, 2, 3, 4, 5, 6, 7, 8};
int (*q)[2][2] = arr;