Страницы

Поиск по вопросам

понедельник, 16 декабря 2019 г.

Вложенные функции в C

#c #функции


1) Являются ли вложенные функции исключительно расширением компиляторов, или же они
появились в стандарте C11?

2) Вложенная функция имеет доступ ко всему, что лежит перед ней в ее области определения.
С одной стороны, это удобно, получается нечто, напоминающее лямбды, но с другой стороны
- появляются сколькие проблемы.

Например, такие:

void a(const int _i)
{
    void b(void)
    {
        printf("_i: %i", _i);
    }
}

// Технически, мы можем вызвать b() за пределами a(),
// но тогда непонятно, к чему мы обратимся, используя _i.


Я хотел бы разобраться, что можно делать с такими функциями, а что нельзя.

PS. Понятно, что вложенные функции опасны и имеют неочевидные подводные камни, но
в некоторых случаях альтернативные решения еще хуже (например, макросы). В определенных
ситуациях бывает удобно вынести повторяющиеся действия во вложенные функции. Или, к
примеру, задать обработчик прямо перед его использованием, например так:

FILE *f = fopen("data", "wb");
// ...

void handler(void *_n)
{
    list_node *n = (list_node*)_n;
    fwrite(n->data, n->size, 1, f);
}

list_for_each(list, handler);

    


Ответы

Ответ 1



Это расширение gcc: https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html Имя вложенной функции имеет локальную область видимости, т.е. нельзя вызвать b за пределами a.

strict aliasing и char*

#cpp #c #strict_aliasing


Пытаюсь понять, в какой мере strict aliasing rule не касается char.

Во многих источниках делается акцент на том, что char может накладываться на любой
тип, но не наоборот. Что это значит?

Допустим:

int i;

int *pi = &i;
char *pc = (char*)&i;

// Первый случай.
*pc = 0;
*pi = 1;
// *pc != 0?

// Второй случай.
*pi = 0;
*pc = 1;
// *pi != 0?


Исключим из рассмотрения порядок байтов, требования выравнивания и прочие штуки.  

Верно ли я понимаю, что в связи с однонаправленностью описанного правила, один из
описанных случаев будет корректен, а другой - вызовет неопределенное поведение?

Или же правило описывает иную ситуацию, и оба приведенных случая не выльются в неопределенное
поведение?

Идентично ли поведение C и C++?

Я совершенно запутался с этим sa...
    


Ответы

Ответ 1



Во-первых что такое "strict aliasing" (в двух словах) - это следствие из ограниченности перечня типов выражений, для которых в стандарте определяется поведение при обращение к объекту определенного типа. Это следствие заключается в том, что у компилятора появляется возможность считать, что указатели (и ссылки) несовместных типов никогда не указывают на одно и то же место в памяти, то бишь что они не являются алиасами одного и того же объекта. Более формально этот перечень определен так: 8.2 Properties of expressions [expr.prop] 11 If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined: 63 (11.1) — the dynamic type of the object, (11.2) — a cv-qualified version of the dynamic type of the object, (11.3) — a type similar (as defined in 7.5) to the dynamic type of the object, (11.4) — a type that is the signed or unsigned type corresponding to the dynamic type of the object, (11.5) — a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object, (11.6) — an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union), (11.7) — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object, (11.8) — a char, unsigned char, or std::byte type. Что же особенного в char? Дело в том, что модель памяти основана на адресации байт и все объекты в языке имеют байтовое представление. Последний пункт в перечне как раз разрешает получение доступа к байтовому представлению (object representation). Однако заметьте, что эти правила относятся непосредственно к доступу к объекту, то бишь левой части выражения *pc = 0;. А само присваивание работает потому что для тривиально-копируемых объектов разрешено копирование байт туда-сюда. Далее, приведенный в вопросе "второй случай" на самом деле ничем не отличается от первого. Обратный пример тут должен был бы выглядеть вот так: alignas(int) char bytes[sizeof(int)]{}; char * pc{static_cast(bytes)}; int * pi{reinterpret_cast(pc)}; *pi = 1; // неопределенное поведение! Но это еще не все, дело в том, что в имеется возможность размещать объекты в памяти (provide storage)! alignas(int) char bytes[sizeof(int)]{}; char * pc{static_cast(bytes)}; int * pi1{new(pc) int{}}; *pi1 = 1; // определенное поведение! int * pi2{reinterpret_cast(pc)}; *pi2 = 1; // (внезапно) по-прежнему неопределенное поведение, хотя pi2 == pi1!

Проблема с получением адреса Google Maps Geocode

#php #google_maps_api #google_maps


https://maps.googleapis.com/maps/api/geocode/json?latlng=" . $latitude .",". $longitude
."&sensor=false&key=API_KEY
Проблема такая, получаю в ответ неправильный адрес, как исправить?

Пример того, что я получаю

    {
   "plus_code" : {
      "compound_code" : "5C9R+3C Yerevan, Armenia",
      "global_code" : "8HG65C9R+3C"
   },
   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "жилое",
               "short_name" : "жилое",
               "types" : [ "premise" ]
            },
            {
               "long_name" : "Bangladesh",
               "short_name" : "Bangladesh",
               "types" : [ "political", "sublocality", "sublocality_level_1" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "жилое, Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.1678554,
                  "lng" : 44.4411725
               },
               "southwest" : {
                  "lat" : 40.1674516,
                  "lng" : 44.4409767
               }
            },
            "location" : {
               "lat" : 40.1676558,
               "lng" : 44.4410813
            },
            "location_type" : "ROOFTOP",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.1690024802915,
                  "lng" : 44.4424235802915
               },
               "southwest" : {
                  "lat" : 40.1663045197085,
                  "lng" : 44.4397256197085
               }
            }
         },
         "place_id" : "ChIJN4orDd-9akARr_CHIzBo7uE",
         "types" : [ "premise" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "Unnamed Road",
               "short_name" : "Unnamed Road",
               "types" : [ "route" ]
            },
            {
               "long_name" : "Bangladesh",
               "short_name" : "Bangladesh",
               "types" : [ "political", "sublocality", "sublocality_level_1" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Unnamed Road, Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.1678113,
                  "lng" : 44.4409177
               },
               "southwest" : {
                  "lat" : 40.1671363,
                  "lng" : 44.4394916
               }
            },
            "location" : {
               "lat" : 40.1673747,
               "lng" : 44.440349
            },
            "location_type" : "GEOMETRIC_CENTER",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.1688227802915,
                  "lng" : 44.4415536302915
               },
               "southwest" : {
                  "lat" : 40.1661248197085,
                  "lng" : 44.4388556697085
               }
            }
         },
         "place_id" : "ChIJX5kLet-9akARxu92iLmBBCk",
         "types" : [ "route" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "B1",
               "short_name" : "B1",
               "types" : [ "neighborhood", "political" ]
            },
            {
               "long_name" : "Malatia-Sebastia",
               "short_name" : "Malatia-Sebastia",
               "types" : [ "political", "sublocality", "sublocality_level_1" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "B1, Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.1738564,
                  "lng" : 44.4460917
               },
               "southwest" : {
                  "lat" : 40.1651662,
                  "lng" : 44.4371009
               }
            },
            "location" : {
               "lat" : 40.1698302,
               "lng" : 44.441828
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.1738564,
                  "lng" : 44.4460917
               },
               "southwest" : {
                  "lat" : 40.1651662,
                  "lng" : 44.4371009
               }
            }
         },
         "place_id" : "ChIJE4fvRt69akARZwyHPF6rPiA",
         "types" : [ "neighborhood", "political" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "Malatia-Sebastia",
               "short_name" : "Malatia-Sebastia",
               "types" : [ "political", "sublocality", "sublocality_level_1" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Malatia-Sebastia, Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.2256632,
                  "lng" : 44.48988139999999
               },
               "southwest" : {
                  "lat" : 40.1447431,
                  "lng" : 44.3619347
               }
            },
            "location" : {
               "lat" : 40.1686452,
               "lng" : 44.45749199999999
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.2256632,
                  "lng" : 44.48988139999999
               },
               "southwest" : {
                  "lat" : 40.1447431,
                  "lng" : 44.3619347
               }
            }
         },
         "place_id" : "ChIJcabfJdG9akARS3WuMhvvZcI",
         "types" : [ "political", "sublocality", "sublocality_level_1" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "locality", "political" ]
            },
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.2426667,
                  "lng" : 44.6150493
               },
               "southwest" : {
                  "lat" : 40.0641141,
                  "lng" : 44.3620849
               }
            },
            "location" : {
               "lat" : 40.1872023,
               "lng" : 44.515209
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.2426667,
                  "lng" : 44.6150493
               },
               "southwest" : {
                  "lat" : 40.0641141,
                  "lng" : 44.3620849
               }
            }
         },
         "place_id" : "ChIJW4v8uNqiakARalLah655FD0",
         "types" : [ "locality", "political" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "Yerevan",
               "short_name" : "Yerevan",
               "types" : [ "administrative_area_level_1", "political" ]
            },
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Yerevan, Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 40.261712,
                  "lng" : 44.66696109999999
               },
               "southwest" : {
                  "lat" : 40.08440600000001,
                  "lng" : 44.416932
               }
            },
            "location" : {
               "lat" : 40.1794197,
               "lng" : 44.5408413
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 40.261712,
                  "lng" : 44.66696109999999
               },
               "southwest" : {
                  "lat" : 40.08440600000001,
                  "lng" : 44.416932
               }
            }
         },
         "place_id" : "ChIJc-dHAcOiakAR9TDRSvqQzRU",
         "types" : [ "administrative_area_level_1", "political" ]
      },
      {
         "address_components" : [
            {
               "long_name" : "Armenia",
               "short_name" : "AM",
               "types" : [ "country", "political" ]
            }
         ],
         "formatted_address" : "Armenia",
         "geometry" : {
            "bounds" : {
               "northeast" : {
                  "lat" : 41.300993,
                  "lng" : 46.6342219
               },
               "southwest" : {
                  "lat" : 38.840244,
                  "lng" : 43.4472601
               }
            },
            "location" : {
               "lat" : 40.069099,
               "lng" : 45.038189
            },
            "location_type" : "APPROXIMATE",
            "viewport" : {
               "northeast" : {
                  "lat" : 41.300993,
                  "lng" : 46.6342219
               },
               "southwest" : {
                  "lat" : 38.840244,
                  "lng" : 43.4472601
               }
            }
         },
         "place_id" : "ChIJx7pz54RWFUARIy2C63p1tNA",
         "types" : [ "country", "political" ]
      }
   ],
   "status" : "OK"
}


вместо номера и адреса дома получаю "жилой дом".
К примеру на сайте https://www.gps-coordinates.net , который также использует гугл
мапс, все адреса правильно выводятся 
    


Ответы

Ответ 1



По данному району Еревана у Гугл нет информации о номерах домов. https://www.google.ru/maps/@40.1676681,44.440202,19.39z Зато на ОСМ есть номера домов https://www.openstreetmap.org/#map=19/40.16770/44.44048 Тут 2 варианта решения. 1. Сделать геокодер на основе ОСМ и других доступных данных на интересующую область. Плюс подхода в том, что вы получаете независимость, гибкость, возможность редактировать и дополнять информацию, улучшая результат. 2. Использовать готовые сторонние сервисы, типа https://opencagedata.com Плюс подхода в быстроте подключения. Не нужно разрабатывать API и анализировать данные. Можно сочетать оба варианта, проверяя результат, выводить лучший.

Ответ 2



У гугла такое может быть, не использовав другие сервисы вы не сможете определить адрес. http://joxi.ru/1A5Go11tDQjlqm т.е. даже на google maps нет адресов у зданий. А https://www.gps-coordinates.net/ использует https://opencagedata.com/ что вы можете собственно и использовать вместо гугла, сервис даёт 2500 запросов в день бесплатно, гугл даёт 70 000 запросов в месяц бесплатно. Посмотреть работу демо можно тут https://opencagedata.com/demo

Яндекс апи: Как определить город?

#javascript #yandex_maps_api #геолокация